Pharo Smalltalk - How can I check if a message conforms to a protocol defined in another object's Class? - smalltalk

I'm looking at this form an Objective-C background so be gentle. The experiment looks like this:
Object1 has an instance variable named delegate.
Object1 receives a message and the proceeds to check if delegate implements a specific protocol (whose name is known beforehand), if it does, then it checks if the message is among the protocol's implemented methods. It then makes a decision on how to interact with the delegate and so on.
In Objective-C one has to define clear Protocols, usually stored in different files, and conforming to a protocol is checked by the compiler. In Pharo I can't seem to find how to check for this kind of information even though the Browser has a whole column dedicated to protocols, and beside grouping methods they seem to do very little.

Here are some few alternatives that could help you with this:
Get the collection of all selectors that populate the object's class:
anObject class selectors
Get the collection of all selectors that populate the object's class and all its superclasses:
anObject class allSelectors
Ask the class whether it implements a given message (for its instances):
anObject class canUnderstand: #putTheSelectorHere
Ask the object whether it understands a given message:
anObject respondsTo: #methodSelectorHere
Use the MessageNotUnderstood mechanism:
(see explanation below)
In 1 and 2 above you can use the returned collections to check whether they include a certain selector you are interested in. Features 3, 4 and 5 have a more dynamic nature. For example, you can refine the #doesNotUnderstand: method in your class as follows:
MyClass >> #doesNotUnderstand: aMessage
(delegate respondsTo: aMessage selector)
ifTrue: [^delegate
perform: aMessage selector
withArguments: aMessage arguments].
^super doesNotUnderstand: aMessage
This way, if your object receives a message that it does not understand, it will first receive the #doesNotUnderstand: message (without you having to do anything for this to happen) and here you could decide (e.g., by using the #respondsTo: message) whether to delegate it or not. If not, you can just relay on the default behavior (super doesNotUnderstand:) which would signal de MessageNotUnderstood exception.
Of course, there is a 6th option, which would be for the sender of the message to handle the MNU exception, but I don't think this is what you are looking for here.

There is the proxies work in Ghost/Marea and the original Smalltalk wrappers to the rescue I'm not sure the proxies have been updated for the latest Pharo version. Latest ghost version seems to be here

Related

Pharo Smalltalk - Is it possible to assign super to some other instance after the Object has been instantiated?

Suppose we have oneInstance and secondInstance, one of SomeClass and one OtherClass with the example Class hierarchy below:
oneInstance
Object
- SomeClass (some variables of it's own, nothing major)
secondInstance
Object
- SomethingClass
- OtherClass (just about any class in the tree here)
Is it possible, at runtime, to change oneInstance so that it's "super" message sends reach secondInstance.
oneInstance and secondInstance merge essentially making oneInstance work as if they are one object and the structure appear as if they were instantiated from something like and:
secondInstance wraps around oneInstance
Object
- SomethingClass
- OtherClass (just about any class in the tree here)
- SomeClass (some variables of it's own, nothing major)
The simplest would be if I could assign super := secondInstance on oneInstance for a bit and then change it back :D
PS. Essentially we are reclassing oneInstance by having secondInstance as it's "super" they are now one object with the state of both presuming oneInstance is subclassed from Object with no other state but it's own. Mostly a hack to use the inheritance chain's default method lookup to my advantage. Closest thing I could find is Object Slicing https://en.wikipedia.org/wiki/Object_slicing
Another way to look at it would be this:
secondInstance is receiving messages, it's an instance of OtherClass, all is well. Some of the messages it receives are not in OtherClass so method lookup goes up the inheritance chain to SomethingClass and then to Object, ProtoObject, etc. and finally they should be forwarded to the other instance. This process should be entirely transparent.
First of all, in Pharo and Squeak (and most Smalltalks) you are always at runtime. So obviously, if its possible to do something, its possible to do it at "runtime". :)
Generally messing around with meta capabilities for "regular code" leads to really deceptive code that is hard to debug, both for you and especially others. So to implement #doesNotUnderstand: and using #respondsTo: etc, is normally "bad style" unless you REALLY have to do these things.
An obvious example for transparent forwarder objects is proxies for OODBS - but there really aren't many good examples.
But to answer more precisely - in your implementation of #doesNotUnderstand: - just query if self respondsTo: aMessage selector (or similar) and make your decision to delegate or not based on that.

Can an ObjC class object conform to a protocol?

Is there a way to indicate to the compiler that a class object conforms to a protocol?
As I understand, by creating +(void)foo class methods, an instance of that class object will have those methods as instance methods. So, as long as I create +(void)foo methods for all required protocol methods, I can have a class object act as a delegate.
My problem of course is that in the class's header file, I only know how to indicate that instances of the class conform to the protocol (as is typically the case). So, the best I've figured out is to cast the class object like so:
something.delegate = (id<SomethingDelegate>)[self class]
Any ideas?
Related, but different:
ObjC: is there such a thing as a "class protocol"?
What you're doing now is correct as it will silence warnings which is your goal. You will be sending the class object messages defined in the protocol for instances which is a bit confusing, but the runtime doesn't care.
Think about it this way: you want to set a delegate to an object that responds to the messages defined in the protocol. Your class does this, and your class is also an object. Therefore, you should treat your class like an object that conforms to that protocol. Therefore, what you've written is completely correct (based on what you're trying to do).
One thing to note, though, is this class will not properly respond to conformsToProtocol:. This is generally okay for a delegate setup anyway (delegates don't usually check if the class conforms — they just check if it can respond to a selector).
As a side note, one thing you can do syntactically is:
Class<SomethingDelegate> variable = (Class<SomethingDelegate>)[self class];
The difference here is that the compiler will use the class methods from the protocol instead of instance messages. This is not what you want in your case, though.
There is no Objective-C syntax to indicate that a metaclass conforms to a protocol.
I think you can do it at runtime, by using class_addProtocol on the metaclass. But I haven't tried it.
I guess you could also write a +conformsToProtocol: method on your class, and lie about your conformance. This could have unexpected side-effects, since there's already a +conformsToProtocol: on NSObject (in addition to -conformsToProtocol:).
Neither of these will eliminate the need for a cast to shut the compiler up. Just use a singleton.

Introspect parameter of type: id to decide whether it is a class or a protocol

I have the following method:
-(void)SomeMethod:(id)classOrProtocol;
It will be called like this:
[self someMethod:#protocol(SomeProtocol)];
Or
[self someMethod:[SomeClass class]];
Within the method body I need to decide if |classOrProtocol| is:
Any Class(Class) OR Any Protocol(Protocol) OR Anything else
[[classOrProtocol class] isKindOfClass: [Protocol class]]
Results in a (build)error:
Receiver 'Protocol' is a forward class and corresponding #interface may not exist
So how can I tell a Protocol from a Class from anything else?
In Objective-C 2 (i.e. unless you use 32 bit runtime on OS X) Protocol is defined to be just a forward class, see /usr/include/objc/runtime.h. The real interface is nowhere declared. You can try to include /usr/inlcude/objc/Protocol.h by saying
#import <objc/Protocol.h>
but as is written there, no method is publicly supported for an instance of Protocol. The only accepted way to deal with Protocol instances is to use runtime functions, given in Objective-C Runtime Reference. It's not even publicly defined whether Protocol is a subclass of anything, and it's not even stated that it implements NSObject protocol. So you can't call any method on it.
Of course you can use the source code of the runtime to see what's going on. Protocol inherits from Object (which is a remnant from pre-OpenStep NeXTSTep), not from NSObject. So you can't use the familiar methods for NSObject-derived objects, including Class of NSObject-derived objects. See the opensourced implementations of Protocol.h and Protocol.m. As you see there, the class Protocol itself doesn't do anything, because every method just casts self to protocol_t and calls a function. In fact, as can be seen from the function _read_images and others in objc-runtime-new.mm, the isa pointer of a Protocol object is set by hand when the executable and libraries are loaded, and never used.
So, don't try to inspect whether an id is a Protocol or not.
If you really need to do this, you can use
id foo=...;
if(foo->isa==class_getClass("Protocol")){
...
}
But, seriously, don't do it.
This is not an issue 'caused by inability to determine whether it's class or protocol. The error is 'caused by missing interface of Protocol class. Make sure you import Protocol.m at the top of your implementation file where you're testing argument's type.
You can also try using NSClassFromString() function which will return Class object or nil. Do note though that if nil is returned it doesn't mean that argument is protocol. It just means that it could be undefined class too!
There is also method NSProtocolFromString which returns appropriate results - Protocol for protocol and nil for undefined protocol.

Objective-C Find all init (constructor methods)

using the "Method * class_copyMethodList(Class cls, unsigned int *outCount)" function one can get a list of all methods that exist on an objective-C class.
I would like to know how to find which of these methods are constructors as I am writing an IOC container. I would like to determine the constructors and their parameter types.
I would like to know how to find which of these methods are
constructors as I am writing an IOC container. I would like to
determine the constructors and their parameter types.
In short, you can't. Or, at the least, you'll find that down this path lies madness.
First, Objective-C does not have constructors. It has initializers, sometimes many, and -- for a properly written class -- only one of which is the designated initializer. There is no way to identify the designated initializer at compile time or run time.
How do I use this with a Method * and no instantiated member of the
class?
You don't. First you allocate an instance of the class, then you initialize the instance.
Overall, this level of abstraction just isn't done in Objective-C outside of academic investigations. It can be done, but it is generally avoided because of the fragility of the resulting solution and the hairball of code-hell that is trying to dynamically support the underlying C ABI (go look at the source to libffi).
If you want to go down this path, then you are far better off either defining a custom abstract class that all of your containers will subclass that can provide the binding logic to the class behind it.
Or use protocols; i.e. a class could implement an IOCBean protocol and one method would be initIOCGoop that is the designated initializer goo.
Doing this generically for all classes is going to be rife with fragility, special cases, and will require a gigantic mess of code that will be difficult to maintain over time.
You can get the method signature by using the following method:
methodSignatureForSelector:
From the documentation:
An NSMethodSignature object records type information for the arguments and return value of a method. It is used to forward messages that the receiving object does not respond to—most notably in the case of distributed objects. You typically create an NSMethodSignature object using NSObject’s methodSignatureForSelector: instance method (on Mac OS X v10.5 and later you can also use signatureWithObjCTypes:). It is then used to create an NSInvocation object, which is passed as the argument to a forwardInvocation: message to send the invocation on to whatever other object can handle the message. In the default case, NSObject invokes doesNotRecognizeSelector:, which raises an exception. For distributed objects, the NSInvocation object is encoded using the information in the NSMethodSignature object and sent to the real object represented by the receiver of the message.

What's the difference between a method and a selector?

What the difference between a method, a selector and a message in Objective-C?
This is a great question.
Selector - a Selector is the name of a method. You're very familiar with these selectors: alloc, init, release, dictionaryWithObjectsAndKeys:, setObject:forKey:, etc. Note that the colon is part of the selector; it's how we identify that this method requires parameters. Also (though it's extremely rare), you can have selectors like this: doFoo:::. This is a method that takes three parameters, and you'd invoke it like [someObject doFoo:arg1 :arg2 :arg3]. There's no requirement that there be letters before each part of the selector components. As I said, this is extremely rare, and you will not find it used in the Cocoa frameworks. You can work with selectors directly in Cocoa. They have the type SEL: SEL aSelector = #selector(doSomething:) or SEL aSelector = NSSelectorFromString(#"doSomething:");
Message - a message is a selector and the arguments you are sending with it. If I say [dictionary setObject:obj forKey:key], then the "message" is the selector setObject:forKey: plus the arguments obj and key. Messages can be encapsulated in an NSInvocation object for later invocation. Messages are sent to a receiver. (ie, the object that "receives" the message).
Method - a method is a combination of a selector and an implementation (and accompanying metadata). The "implementation" is the actual block of code; it's a function pointer (an IMP). An actual method can be retrieved internally using a Method struct (retrievable from the runtime).
Some other related things that you didn't ask for:
Method Signature - a method signature represents the data types returned by and accepted by a method. They can be represented at runtime via an NSMethodSignature and (in some cases) a raw char*.
Implementation - the actual executable code of a method. Its type at runtime is an IMP, and it's really just a function pointer. iOS 4.3 includes a new ability to turn a block into an IMP. This is really cool.
One of the fun things to realize is that the name of a method (the selector) is distinct from the implementation of the method (the IMP). This means that you can swap them around, if you're feeling daring. You can also add and remove methods at runtime, because all you're doing is editing an entry in a hash table: the key is the selector, and the value is the IMP of the method. This allows you to do some really crazy and trippy stuff. It's not for the faint of heart. :)
A method is the implementation which is run when an object or class is asked to perform some action. It is in the scope of its containing class and is therefore different when referenced through some other class. A selector is an identifier which represents the name of a method. It is not related to any specific class or method, and can be used to describe a method of any class, whether it is a class or instance method.
Simply, a selector is like a key in a dictionary. It can tell you what method someone is talking about, but only if you also have the dictionary itself (the class or object). The method is what you get when you ask for the value from the dictionary using the selector as a key.
This site has a good overview of all the terminology in question: http://www.otierney.net/objective-c.html
Check out the link, but I'll give a quick summary:
A method is essentially like a method of function that you are used to in your favourite programming language.
A message (from the article) "A message can be dynamically forwarded to another object. Calling a message on an object in Objective-C doesn't mean that the object implements that message, just that it knows how to respond to it somehow via directly implementing it or forwarding the message to an object that does know how to."
Selectors can mean two things. It can refer to the name of a method, or "refers to the unique identifier that replaces the name when the source code is compiled. Compiled selectors are of type SEL." (from: http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocSelectors.html)