Is it possible to downgrade an object in objective c to its superclass? - objective-c

If I have an instance of class B which is a subclass of class A, is there a way for me to turn my instance of class B into an instance of class A without explicitly writing code to do it?
I do not mean simply downcasting with the standard c syntax.

You may be able to do this with the objc runtime (see the object_setClass(id object, Class cls) in the Objective-C runtime reference. The more important point, however, is that you almost certainly do not want to do this. If your subclass does not follow the Liskov Substituion Principle, it shouldn't be a subclass (i.e. an inheritance relationship is not appropriate and you should choose some other design). You can always invoke the superclass' method implementations with [super someMethod] from within your subclass.

Related

Understanding abstract superclass NSNumber

I am reading some book about objective C ,and they say there that NSNumber is an abstract superclass of many subclasses that we can use .
So, "when we call a method in NSNumber, the appropriate subclass is used" .
This is not going with some other rule that i know :
if superclass A, has subclass B , and you calling a method in the super class A , that is in the subclass B, you can't do that- because inheritance is working all the way up and not down.
So, how is that the superclass (abstract) class- NSNumber, is using its subclass methods ??
What is the hierarchy here ?
Thanks .
It's done through class cluster pattern.
From documentation:
The abstract superclass in a class cluster must declare methods for
creating instances of its private subclasses. It’s the superclass’s
responsibility to dispense an object of the proper subclass based on
the creation method that you invoke—you don’t, and can’t, choose the
class of the instance.
Whenever you create number with some factory method, like +numberWithInt: the factory returns instance of concrete subclass. Afterwards, when you call something like -stringValue: this selector is sent to instance of concrete NSNumber subclass - int in this case.
So, NSNumber factory methods actually does not return NSNumber objects - they return concrete subclasses. Same is true for other Cocoa class clusters - NSArray, NSDictionary, NSSet.
In effect there are classes NSDoubleNumber, NSLongLongNumber, NSIntegerNumber, etc, (made-up names) and you get the appropriate one. But as with all subclassing, if you then call a method of the object via it's superclass type it will respond, invoking the class-specific method appropriate to that instance.
Objective-C muddles things slightly, since if you ask what the class is it won't return "NSDoubleNumber" or whatever but instead returns an essentially meaningless name for the whole cluster, or for a particular subdivision of it.
The point is, you can treat the instances as objects of the single fictitious class "NSNumber" and never need to worry about which subclass you actually have.
(BTW, similar things are true of NSArray, NSDictionary, and a number of other classes.)

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.

Objective-C 2.0 and Categories

In objective-c if I have a class such as "Foo", and have a category for that class "Foo (bar)", but do not implement all the methods declared in the category, would I have to redeclare them in a subclass before I define them? My book says yes (not sure if this is a mistake, or has been changed), I don't see why this is the case.
Basically how do categories apply to subclasses?
Categories are orthogonal to class hierarchy. They apply to the class on where they are defined. At runtime, the category methods are added to the method table of the class. Subclasses can use them as if they were regular methods.
Be sure to (re-)read this chapter of Objective-C Programming Language about the subject.
If you want to override a category method in a subclass, you can to either by declaring it in the class interface, or by declaring a category for the subclass.
Hope it helps.
You don't need to redeclare the method, but you must be able to "see" the declaration if you are calling it internally. (i.e. #import 'Foo+bar.h' in your subclasses .m).
It is, however, not a good idea to declare a method but not implement it. Your application will crash if -[Foo someDeclaredButNotImplementdMethod] is called. At least provide an empty implementations (e.g. - (void)someDeclaredButNotImplementdMethod {}).

How to avoid overriding of methods in subclass in objective c

Can anyone please guide me on how to avoid overriding of superclass methods in subclass in Objective-C, like the "final" concept in Java.
You can't. You can't even be sure that a leaf class's methods are the ones you supplied, because we can use the Objective-C runtime library to replace method implementations in a running application. That's a deliberate feature of the runtime library's design.
Well I'm not sure about a "final" equivalent in objective c but if there are methods in a super class that you don't want called just don't write that particular method in your sub class
Plus I think a method written with "+" prefix as opposed to "-" is a class method and not an instance method so that method should always be the same.

Why subclass NSObject?

What is the purpose/use of NSObject in Objective-C? I see classes that extend NSObject like this:
#interface Fraction : NSObject
In C++ or Java, we don't use any variables like NSObject even though we have preprocessor directives and import statements in both Objective-C and Java.
Why do classes explicitly inherit from NSObject in Objective-C? What are the consequences of not declaring inheritance from NSObject?
We use NSObject to explicitly state what a given class inherits from. I'm not sure about C++, but in Java there's something similar - the Object class. The only difference is that Java doesn't require that classes explicitly descend from Object - the language assumes anything that doesn't have a specified parent class descends from Object. Objective-C is different because it allows you to define different root classes - you are allowed to make a class that doesn't inherit from NSObject.
An example of such a different root class is NSProxy.
Have a look at the GNUstep NSObject source, it shows how the methods interact with the objective-c runtime through C functions.
+ (id) allocWithZone:(NSZone*)z
{
return NSAllocateObject(self, 0, z);
}
- (void) dealloc
{
NSDeallocateObject (self);
}
+ (BOOL) isSubclassOfClass: (Class)aClass
{
return GSObjCIsKindOf(self, aClass);
}
Since object-oriented languages have the concept of an inheritance, in any inheritance hierarchy there is a root class. In Java, the default parent class (if none is provided) is java.lang.Object, whereas in Objective-C, if you don't explicitly declare a parent class, you don't get one. Essentially, your class becomes a root class itself. This is a common mistake among Objective-C newcomers, since you normally want to inherit from NSObject in such cases.
While often problematic and puzzling, this actually allows quite a bit of flexibility, since you can define your own class hierarchies that act completely differently from NSObject. (Java doesn't allow you to do this at all.) On the other hand, unless you know what you're doing, it's easy to get yourself into trouble this way. Fortunately, the compiler will provide warnings if you call a method not defined by a class with no declared parent class, such as those you would normally expect to inherit from NSObject.
As for the "use" of NSObject, check out the documentation of the NSObject class and NSObject protocol. They define common methods used for object allocation, memory management, comparison, hashing, printing descriptions, checking class membership, querying whether objects respond to a selector, etc. Basically, NSObject is "good for" providing the core functionality of Objective-C objects free of charge.
All classes don't necessarily inherit from NSObject but it is the core for many of the classes because it provides things like alloc, retain, and release.
NSObject is the root class of all classes. In my estimation, it's 3 most basic functions are to allocate and initialize memory for you (alloc & init), as well as provide a description function.
Objective-C is all about objects sending messages to other objects -- so NSObject exists to provide that basic functionality.
If this sounds strange to you, you may wish to read more about programming paradigms, particularly object-oriented programming....In a nutshell, however, Objective C is a simple extension to the C language. C gets you the ability to program computer memory, numbers, and characters, but do anything else (like use strings, or show views, for example) you need the extension part, and NSObject is the beginning of that extension.
It may be a useful exercise to pick a class (like NSString, or any for that matter), and follow it's superclasses back to NSObject, to see what functionality each class added.
Hope that helps...
NSObject
The root class of most Objective-C class hierarchies, from which
subclasses inherit a basic interface to the runtime system and the
ability to behave as Objective-C objects.
From Apple documentation - https://developer.apple.com/documentation/objectivec/nsobject.
Basically, most of OOP programming languages explicitly or implicitly specify base class or base functionality. Otherwise you cannot build system where objects communicate with each other. Properties, memory management, message sending mechanism are partly or completely provided or supported by NSObject. Apple provide parts of the Objective-C implementation - https://opensource.apple.com/source/objc4/objc4-723/runtime/NSObject.mm.auto.html, where it's possible to see what is actually inside NSObject.
Also because Objective-C is a language from C-family, so compiler and linker needs to calculate how to layout object in memory and where put and find methods, that's only possible if you know how each of the classes/instances lays in memory and where. In case of Objective-C all base classes (NSObject, NSProxy, etc) have specification of that, so it's possible to calculate their size and add on top all inherited stuff - https://clang.llvm.org/compatibility.html#objective-c.
Consequently compiler don't let to leave a class without base class. So in the end class inheritance should lead to one of the root classes. Here is the error that appears if you don't specify it (from Xcode):
Class 'ClassWithoutBaseClass' defined without specifying a base class