Test method existence on Objects - oop

I have a cell array of Matlab objects, something like:
objs = {Object1(), Object2(), Object3()};
These objects are all of different types. Some of them will have a method, let's call it myMethod(). I want to do something like:
for o = objs
if hasMethod(o, 'myMethod()')
o.myMethod();
end
end
and my difficulty is that I don't know how to do hasMethod - exist doesn't seem helpful here.
I could use a try - catch, but I'd rather do something neater. Is there a way to do this? Should I just change my design instead?

Another option is to use the meta class.
obmeta = metaclass(ob);
methodNames = cellfun(#(x){x.Name},obmeta.Methods);
You can also get additional information from obmeta.Methods like
Amount of input/output parameters.
Access type
In which class the method is defined.
Also, metaclass can be constructed from the name of the class, without an instance, which can be an advantage in some situations.

Ah, found it. Not very exciting - you can get a list of methods with the methods command. So to check if an object has a method,
if any(strcmp(methods(o), 'myMethod'))
o.myMethod();
end

Very close! If you had written the function name a bit differently you would've stumbled upon the following built-in:
if ismethod(o, 'myMethod')
o.myMethod();
end
Documentation: ismethod.

Why would you want to do that? You'd better have a good reason :p
Better make them inherit a general function from a superclass. Then you can just call that function for all of them, instead of looking up which class it is/checking if a function exists and then calling a function depending on the result (which is imo not very OO)

One simple option is to use the function EXIST (along with the function CLASS) to check if the method exists for the given class:
if exist(['#' class(o) '/myMethod'])
o.myMethod();
end
Another option is to use the function WHICH to perform the check like this:
if ~isempty(which([class(o) '/myMethod']))
o.myMethod();
end

Related

Inherit from table returned from function

There is an API provided function, let's call it createBase which returns a table (object). I want to add methods to this table, but I can't just do x = createBase() and then function x:foo() because I have another function similar to createBase, but it's createExtended. It might be easier to explain with the code I have so far:
import api --I don't know how you'd do this in vanilla Lua, I'd use os.loadAPI("api") but that's computercraft specific, I think
Extended = {}
function Extended:foo()
print("foo from extended")
end
function createExtended(params)
x = api.createBase(params)
Extended.__index = x
return Extended --this is obviously wrong: you can't return a class and expect it to be an object
end
Of course, this doesn't work: but I don't know how I might make it work either. Let's assume the table returned by createBase has a function called bar which just prints bar from base. With this test code, the following outputs are given:
e = createExtended()
e.foo() --prints "foo from extended"
e.bar() --nil, therefor error
How can I make this possible, short of defining function x.bar() inside createExtended?
Thanks in advance.
The very simplest way is to attach the method to it directly, instead of using a metatable.
local function extend(super_instance)
super_instance.newMethod = newMethod
return super_instance
end
local function createExtended(...)
return extend(createSuper(...))
end
This will work, unless your superclass uses __newindex (for example, preventing you from writing to unknown properties/methods), or iterates over the keys using pairs or next, since it will now have an additional key.
If for some reason you cannot modify the object, you will instead have to 'wrap' it up.
You could make a new instance which "proxies" all of its methods, properties, and operators to another instance, except that it adds additional fields and methods.
local function extend(super_instance)
local extended_instance = {newMethod = newMethod}
-- and also `__add`, `__mul`, etc as needed
return setmetatable(extended_instance, {__index = super_instance, __newindex = super_instance})
end
local function createExtended(...)
return extend(createSuper(...))
end
This will work for simple classes, but won't work for all uses:
Table iteration like pairs and next won't find the keys from the original table, since they're not actually there. If the superclass inspects the metatable of the object it is given (or if the superclass is actually a userdata), it will also not work, since you'll find the extension metatable instead.
However, many pure-Lua classes will not do those things, so this is still a fairly simple approach that will probably work for you.
You could also do something similar to Go; instead of having a way to 'extend' a class, you simply embed that class as a field and offer convenience to directly calling methods on the wrapping class that just call the methods on the 'extended' class.
This is slightly complicated by how 'methods' work in Lua. You can't tell if a property is a function-that-is-a-property or if it's actually a method. The code below assumes that all of the properties with type(v) == "function" are actually methods, which will usually be true, but may not actually be for your specific case.
In the worst case, you could just manually maintain the list of methods/properties you want to 'proxy', but depending on how many classes you need to proxy and how many properties they have, that could become unwieldy.
local function extend(super_instance)
return setmetatable({
newMethod = newMethod, -- also could be provided via a more complicated __index
}, {
__index = function(self, k)
-- Proxy everything but `newMethod` to `super_instance`.
local super_field = super_instance[k]
if type(super_field) == "function" then
-- Assume the access is for getting a method, since it's a function.
return function(self2, ...)
assert(self == self2) -- assume it's being called like a method
return super_field(super_instance, ...)
end
end
return super_field
end,
-- similar __newindex and __add, etc. if necessary
})
end
local function createExtended(...)
return extend(createSuper(...))
end

How to name a function that creates fixpoint results on its input?

I have a function that decorates a string. If the decorated string is again fed to the function, it is guaranteed not to change. How is the standard naming convention for such a function? I'll probably create a namespace because I need to have a few of those functions.
I've come up with:
repetition_safe.decorate(me);
fixpoint_gen.decorate(me);
one_time_effect.decorate(me);
but I don't really like any of these.
How would you name the namespace or function?
How about:
StringDecorator.MakeImmutable(input);
I think "MakeImmutable" is better than "Decorate" as the later is ambiguous i.e. a user reading the code won't know what "decorate" does, whereas "makeImmutable" will inform the user that this function will make the input string immutable/non-changable.

Stubbing a dictionary in Rhino.Mocks

I have a read-only dictionary on a dependency that I'd like to be able to stub with return values, and check that assignments to it have happened.
I was hoping that Rhino.Mocks would create an empty dictionary for me by default, but unfortunately it doesn't. Since it is read-only, I can't create a new dictionary and assign it to that property.
I was hoping to be able to stub it instead. From what I understand, the C# syntax for this would looking something like this:
m.Stub(x => x.myProperty).Return("abc");
So I was hoping that this would work for VB:
m.Stub(sub(x) x.myProperty).Return("abc");
But it doesn't (compiler error). Any ideas on how to accomplish this? I'm open to the Expect/Verify syntax if it can accomplish this...
Using Function will do the trick:
m.Stub(Function(x) x.myProperty).Return("abc")
If you want to verify whether myProperty got called you could use Expect instead of Stub:
m.Expect(Function(x) x.myProperty).Return("abc")
// Some code here
m.VerifyAllExpectations()

Function without return type

In my project (which I inherited from someone) there are a lot of functions like:
Public Function DoSomething(ByVal s As String)
' Do something to public properties
End Function
And they are called like this:
DoSomething(s)
So the return value is ignored (which is object, as I see in the docs). Is it safe to change all these functions to Subs? Could I break something which isn't so obvious?
Should be safe. That's what Subs are for, this is really bad style by your predecessor.
Is there any specific reason you want to convert to Subs? From your code the Function has no return type - in this situation I can't see there being any problem.

How to access the object itself in With ... End With

Some code to illustrate my question:
With Test.AnObject
.Something = 1337
.AnotherThing = "Hello"
''// why can't I do this to pass the object itself:
Test2.Subroutine(.)
''// ... and is there an equivalent, other than repeating the object in With?
End With
There is no way to refer to the object referenced in the With statement, other than repeating the name of the object itself.
EDIT
If you really want to, you could modify your an object to return a reference to itself
Public Function Self() as TypeOfAnObject
Return Me
End Get
Then you could use the following code
With Test.AnObject
Test2.Subroutine(.Self())
End With
Finally, if you cannot modify the code for an object, you could (but not necessarily should) accomplish the same thing via an extension method. One generic solution is:
' Define in a Module
<Extension()>
Public Function Self(Of T)(target As T) As T
Return target
End Function
called like so:
Test2.Subroutine(.Self())
or
With 1
a = .Self() + 2 ' a now equals 3
End With
I suspect you'll have to repeat yourself. If the expression (to get the object) is expensive, then perhaps drop it into a variable first, and either use that variable in the With, or drop the With completely:
tmp = Test.AnObject;
tmp.Something = 1337;
...
Test2.Subroutine(tmp);
As others have said, you're going to have to write
Test2.Subroutine(Test.AnObject)
This is a good example of why it's worth being a little careful with the With construct in VB.Net. My view is that to make it worth using at all, you really need to be setting more than one or two properties, and/or calling more than one or two methods on the object in the With statement.
When there are lots, and you're not interspersing the .SomeProperty = , or .DoSomething, with other things, it's a terrific aid to readability.
Conversely, a few dots sprinkled amongst a load of other stuff is actually a lot harder to read than not using With at all.
In this case, . characters on their own could easily get lost visually, although of course, it would be syntactically consistent.
I guess they just chose not to implement it. VB isn't really the sort of language where they want to encourage single character language elements, and as a heavy user of VB.Net, I broadly agree with that.
Bottom line: if you're using a With clause with many contained elements, having to refer to the object itself isn't that big a deal. If you're using it with just one or two, maybe better not to use a With clause in the first place.
I'm not sure this is an "answer", per se, but it does illustrate another reason to want a short-hand reference to the parent in a With.
Here's a code sample using a "bare With" (that's what I call it, anyway):
With New frmMySubForm
.lblLinkLabel.Links.Add(New LinkLabel.Link With {.Name = "link", .LinkData = "someUrl", .Start = .lblLinkLabel.Text.IndexOf("link"), .Length = "link".Length})
...
End With
But you actually can't code that because in the term .Start = .lblLinkLabel.Text.IndexOf("link") the compiler expects anything starting with . to be a member of LinkLabel.Link, which .lblLinkLabel isn't.
What would be good, I think, is to be able to write something like:
With New frmMySubForm
.lblLinkLabel.Links.Add(New LinkLabel.Link With {.Name = "link", .LinkData = "someUrl", .Start = Me.lblLinkLabel.Text.IndexOf("link"), .Length = "link".Length})
...
End With
where Me in this scope is taken to be New frmMySubForm.
Yes, I realize that I'm being picky and I could easily assign a variable, etc. But the example form is something I use a lot simply out of preference.