multiple inheritance in Objective C [duplicate] - objective-c

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Objective C multiple inheritance
Hi,
Objective C does not support multiple inheritance. I am porting the cpp code to Objective C
How to declare this definition in Objective C?
class A:protected B,protected C
{
//stmts;
}
#interface A:protected B,protected C
{
}
#end
is not possible.

No.
Not only that, all super classes are the equivalent of public classes in C++.
In Objective-C we don't use inheritance as much as in the C++ alike languages, we tend to use composition more. For example, if you have an array-like collection, you won't normally subclass NSArray, you will create a new class that possibly uses an NSArray as its "backing store".
There are tricks you can do to forward messages that your new class doesn't respond to to its NSArray instance variable. For example, you can override -forwardingTargetForSelector: so that any messages your object doesn't respond to are forwarded to the underlying NSArray. If you think about it, you can implement a home made multiple inheritance hack with this.
edit
An example:
If you have a class that provides array like collection functionality and you want all the NSArray methods, you can do this:
#interface MyClass : NSObject
{
#private
NSArray* backingArray;
}
// declarations of your methods
#end
#implementation MyClass
// implementations for your methods + initialisation
-(id) forwardingTargetForSelector: (SEL) aSelector
{
return backingArray;
}
#end
In reality, you never see code like this for simple cases - people always use categories. If you want to emulate multiple inheritance using this trick, you need an instance variable for each "inherited" class and the method -forwardingTargetForSelector: needs some logic in it based on the selector to decide which object to return. This is going to be quite slow so you can optimise heavily used selectors by implementing them directly as per PeyloW's answer.

Objective-C do not support multiple inheritance, so this is not possible.
Inheritance is a "is-a" relation, one class can only have one is-a relation through inheritance. You can have several is-a relations through protocols (interfaces in Java or C# parlace, or completely abstract class in C++).
Instead of a is-a relation you can model a "has-a" relation. Any object can have any number of has-a relations. In practice you just need to have one instance variable of each class you want. For example:
#interface A : NSObject {
#private
B* _b;
C* _c;
}
// ... stuff
#end
You will need to reimplement all methods from B and C and call down to the contained instance variables as needed. If for example B implements theAnswer then you must also implement it in A as:
-(int)theAnswer {
return [_b theAnswer];
}
It is cumbersome, but this is what you need to do when real multiple inheritance is not available.

Related

Is it possible to extend(heritance) class in Objective-c as is traditionally conceptualised in other languages?

I am having a lot of repeated code throughout my app classes given that some properties & method are stable across all my views.
I am looking to extend whatever class I am working with so that it automatically inherit all properties and methods that I think should be common to those classes.
I looked into the apple guide on extending classes. But I am left confused in the terms of the level of heritance that I can achieve.
I've successfully created Categories on lets say a UIViewController. But that limits me to only be able to declare Methods. I can not declare Properties on my Category and call them in side my Category or in the Extended Class. I want to be able to declare Properties and use it inside and outside my Extended-Class.
Its my first time trying to extend a class in objective-c taking full advantage of heritance but I do not know if it is possible. Am I missing something?
As an example in the code below every time I try to instantiate activityIndicatorView inside my method _activityIndicator it wouldn't recognise it. I've tried #syntetize and #dynamic but it doesn't work
NOTE: I am seeking an answer based on how to achieve heritance of methods and propeties. not highlighting what categories cant do (as I already tried and know I cant have properties there)
My attempt went as far of
#import <UIKit/UIKit.h>
#interface UIViewController (customViewController1)
#property (strong, nonatomic) UIView *activityIndicatorView;
- (void) _activityIndicator;
#end
#import "UIViewController+customViewController1.h"
#implementation UIViewController (customViewController1)
- (void) _activityIndicator {
//......
}
Your question is too broad, plus it is not clear what your problem is. Yes, you can subclass in Objective-C.
This is all very well documented in Apple's document "Object-Oriented Programming with Objective-C", section "The Object Model", subsection "Inheritance".
Categories are a nice way to add functionality while at the same time conforming to an object oriented principle to prefer composition over inheritance.
Categories only add methods, you can't add variables to a class using categories. If the class needs more properties, then it has to be subclassed.
When you use the term “extend”, you're talking about creating a subclass. This is, IIRC, how the term is used in Java and some other languages.
Apple uses the term differently (as Hermann Klecker hinted in his first comment). They literally mean extending an existing class with more functionality (in the form of methods)—that's what categories do. This is the normal English definition; extending something in the real world generally does not create a new thing.
Objective-C supports subclasses, too; it just doesn't call them “extending” the superclass. It's called creating a subclass, which inherits from the superclass.
Strctly spoken you cannot add a property to an existing class any differnt than creating a subclass.
If you cannot halp yourself and subclassing is not an option, then you can extend the class with getters and setters for the property that you want to store within the class.
Instead of really storing it as a member/instance variable/property, which you can't do, you could store the object (it cannto be a scalar, must be an object) in the global space using objc_setAssociatedObject(id object, void *key, id value, objc_AssociationPolicy policy).
This is some sort of global dictionary with two keys, the key itself and the ojbect to which you want to associat the stored object to. In your case that is the object of the type of the exended class. The setter stores it there and the getter receives it from there using objc_getAssociatedObject.
You delete an association by sending nil as value to objc_setAssociatedObject
AFAIK retained associated objects (values) are released shortly after the object that holds the associateion (object) is deallocated.
For further details see the Ojbective-C Runtime Reference https://developer.apple.com/library/ios/documentation/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.html
Just: I do not say that this is strictly following the OO paradigm. :-)

Adding the same category to multiple classes

I have an Objective-C category that I'd like to add to multiple classes without duplicating the code contained in the category. I simply want to add the same methods to multiple classes.
I have existing categories on NSManagedObject subclasses (Book, Chapter, Page) and I would like to add common functionality throughout these subclasses in a clean and maintainable way.
One way would be to add the category to their common superclass (NSManagedObject), but that has the consequence of adding the category's methods to all NSManagedObject subclasses when I want to add the methods to three NSManagedObject subclasses (Book, Chapter, Page).
Another solution would be to subclass NSManagedObject and then have Book, Chapter, and Page inherit from that NSManagedObject subclass. This is the cleanest, most straight forward approach. The big downside with this approach is when the data model changes and Xcode regenerates the subclasses, it will reset them back to inheriting from NSManagedObject instead of SubclassedManagedObject. I'd like to avoid using something like mogenerator/Xmo'd if possible.
Is it possible to add a single category on multiple classes without duplicating code?
Thanks.
maybe it's too late.. But maybe there is one way to do it..
But, you said.. needs to have the same superclass
Category.h
#protocol MyProtocol <NSObject>
- (NSString*)foo;
#end
#interface NSArray (category) <MyProtocol> #end
#interface NSString (category) <MyProtocol> #end
Category.m
#interface NSObject (category) <MyProtocol> #end
#implementation NSObject (category)
- (NSString*)foo
{
return #"bar";
}
#end
I don't like this neither, but it works
Why not make the shared code class level methods in a central class, that you simply call via shell methods in each of your categories?
If your categories are storing associated references you could pass those into the class level methods to act on.
I'm still unaware of a clean way to do this in Objective-C, but with Swift 2.0 this can be implemented using Protocol Extensions by adding functions and/or properties to an existing protocol. The protocol can then be adopted by an arbitrary number of classes, structs, and/or enums.
protocol Numbered {
func number() -> Int
}
extension Numbered {
func number() -> Int {
return Int(arc4random()) % 10
}
}
class Book : Numbered {
}
class Chapter : Numbered {
}
class Page : Numbered {
}
let myBook = Book()
let myChapter = Chapter()
let myPage = Page()
print("myBook.number() = \(myBook.number())")
print("myChapter.number() = \(myChapter.number())")
print("myPage.number() = \(myPage.number())")
correctly implements number() on all three classes (Book, Chapter, Page):
myBook.number() = 5
myChapter.number() = 2
myPage.number() = 8
For the rest of your stuff there, as far as I know you would have to go back and make a common subclass for your three classes to get what you want. But what I can point out is that instead of doing your own isSupported method there it would probably be better to simply use the respondsToSelector method of NSObject to tell if your class implements whatever special method you want those three classes to use, which should be better than checking against all those classes. Defiantly better if you add additional classes as you don't have to maintain or expand that giant list of isMemberOfClass checks
It sounds kind of like you want something like a ruby module. I don't know of any way to do such a thing in objective-c. You could make a protocol and make each of your classes conform to your protocol, but that doesn't solve the problem of sharing implementation of the methods.
Check out this question, it might provide some more insights.
It's a bit of a misnomer to say that providing a category on nsmanagedobject "has the unintended consequence of adding the category's methods to all NSManagedObject subclasses.". The category code is just linked when you include it in a file in which you are using it: you aren't modifying nsmanagedobject.
That said, if the code needs to be aware of its object, you could create a protocol to which those classes conform, and then use conformsToProtocol in your code to do the testing. That's probably a better generic approach than testing for specific class types.

Multiple instance variable types for class?

Is it possible to handle a class with different instance variable types? Let's say I have a class that has two int instance variables, let's call them:
#interface ClassA: NSObject {
int x;
int y;
}
#end
At the same time I want to extend it giving it the possibility to handle a different type on such instance variables like so:
#interface ClassB: ClassA {
double x;
double y;
}
Is this even possible?
I'm pretty sure you can't do that for two reasons:
You can't repeat instance variables (int x, double x).
It's pretty sketchy to inherit from one class, but then want to change the type of its instance variables.
If you don't want to make separate classes for these use-cases, perhaps an abstract superclass would work. If I more about what you're trying to solve, I'd be able to be a bit more helpful in this area.
What it seems like you really want is parametric polymorphism, which Objective-C does not support. Certain Cocoa classes, like the NSNumber family, use an abstract superclass with many concrete subclasses, presumably with different instance variable layouts (like you describe in your question). Then, logic is divided appropriately between the abstract and the specific. This is Cocoa's Class Cluster design pattern, which is a sort of weakened, ad-hoc answer to the parametric polymorphism of languages like C++ and Haskell.
No. You get a compile-time warning of "Duplicate member 'x'" and "Duplicate member 'y'".

Defining categories for protocols in Objective-C?

In Objective-C, I can add methods to existing classes with a category, e.g.
#interface NSString (MyCategory)
- (BOOL) startsWith: (NSString*) prefix;
#end
Is it also possible to do this with protocols, i.e. if there was a NSString protocol, something like:
#interface <NSString> (MyCategory)
- (BOOL) startsWith: (NSString*) prefix;
#end
I want to do this since I have several extensions to NSObject (the class), using only public NSObject methods, and I want those extensions also to work with objects implementing the protocol .
To give a further example, what if I want to write a method logDescription that prints an object's description to the log:
- (void) logDescription {
NSLog(#"%#", [self description]);
}
I can of course add this method to NSObject, but there are other classes that do not inherit from NSObject, where I'd also like to have this method, e.g. NSProxy. Since the method only uses public members of protocol , it would be best to add it to the protocol.
Edit: Java 8 now has this with "virtual extension methods" in interfaces: http://cr.openjdk.java.net/~briangoetz/lambda/Defender%20Methods%20v4.pdf. This is exactly what I would like to do in Objective-C. I did not see this question earning this much attention...
Regards,
Jochen
Short answer: No.
Long answer: how would this work? Imagine you could add methods to existing protocols? How would this work? Imagine we wanted to add another method to NSCoding, say -(NSArray *) codingKeys; This method is a required method that returns an array of the keys used to encoding the object.
The problem is that there are existing classes (like, say NSString) that already implement NSCoding, but don't implement our codingKeys method. What should happen? How would the pre-compiled framework know what to do when this required message gets sent to a class that does not implement it?
You could say "we can add the definition of this method via a category" or "we could say that any methods added via these protocol categories are explicitly optional". Yes, you could do this and theoretically get around the problem I've described above. But if you're going to do that, you might as well just make it a category in the first place, and then check to make sure the class respondsToSelector: before invoking the method.
While it's true that you can't define categories for protocols (and wouldn't want to, because you don't know anything about the existing object), you can define categories in such a way that the code only applies to an object of the given type that has the desired protocol (sort of like C++'s partial template specialization).
The main use for something like this is when you wish to define a category that depends on a customized version of a class. (Imagine that I have UIViewController subclasses that conform to the Foo protocol, meaning they have the foo property, my category code may have need of the foo property, but I can't apply it to the Foo protocol, and if I simply apply it to UIViewController, the code won't compile by default, and forcing it to compile means someone doing introspection, or just screwing up, might call your code which depends on the protocol. A hybrid approach could work like this:
#protocol Foo
- (void)fooMethod
#property (retain) NSString *foo;
#end
#implementation UIViewController (FooCategory)
- (void)fooMethod {
if (![self conformsToProtocol:#protocol(Foo)]) {
return;
}
UIViewController<Foo> *me = (UIViewController<Foo>*) self;
// For the rest of the method, use "me" instead of "self"
NSLog(#"My foo property is \"%#\"", me.foo);
}
#end
With the hybrid approach, you can write the code only once (per class that is supposed to implement the protocol) and be sure that it won't affect instances of the class that don't conform to the protocol.
The downside is that property synthesis/definition still has to happen in the individual subclasses.
extObjC has the NEATEST stuff you can do with Protocols / Categories... first off is #concreteprotocol...
Defines a "concrete protocol," which can provide default implementations of methods within protocol.
An #protocol block should exist in a header file, and a corresponding #concreteprotocol block in an implementation file.
Any object that declares itself to conform to this protocol will receive its method implementations, but only if no method by the same name already exists.
MyProtocol.h
#protocol MyProtocol
#required - (void)someRequiredMethod;
#optional - (void)someOptionalMethod;
#concrete - (BOOL)isConcrete;
MyProtocol.m
#concreteprotocol(MyProtocol) - (BOOL)isConcrete { return YES; } ...
so declaring an object MyDumbObject : NSObject <MyProtocol> will automatically return YES to isConcrete.
Also, they have pcategoryinterface(PROTOCOL,CATEGORY) which "defines the interface for a category named CATEGORY on a protocol PROTOCOL". Protocol categories contain methods that are automatically applied to any class that declares itself to conform to PROTOCOL." There is an accompanying macro you also have to use in your implementation file. See the docs.
Last, but NOT least / not directly related to #protocols is
synthesizeAssociation(CLASS, PROPERTY), which "synthesizes a property for a class using associated objects. This is primarily useful for adding properties to a class within a category. PROPERTY must have been declared with #property in the interface of the specified class (or a category upon it), and must be of object type."
So many of the tools in this library open (way-up) the things you can do with ObjC... from multiple inheritance... to well, your imagination is the limit.
It isn't really meaningful to do so since a protocol can't actually implement the method. A protocol is a way of declaring that you support some methods. Adding a method to this list outside the protocol means that all "conforming" classes accidentally declare the new method even though they don't implement it. If some class implemented the NSObject protocol but did not descend from NSObject, and then you added a method to the protocol, that would break the class's conformance.
You can, however, create a new protocol that includes the old one with a declaration like #protocol SpecialObject <NSObject>.
I think you may be mixing up terms here and there. Extensions, Categories, Protocols, Interfaces and Classes are all different things in Objective-C. In The Objective-C 2.0 Language Apple describes the differences very well, including the benefits and drawbacks to using categories and extensions.
If you think about it, what is a "Category" or "Extension" in the conceptual sense? It's a way of adding functionality to a Class. In Objective-C, protocols are designed to have no implementation. Therefore, how would you add or extend the implementation of something that doesn't have implementation to begin with?
if you're already writing a category, why not just add in the protocol definition in the header right after the category definition?
i.e.
#interface NSString (MyCategory)
- (BOOL) startsWith: (NSString*) prefix;
#end
#protocol MyExtendedProtocolName <NSString>
//Method declarations go here
#end
this way any class that imports the category header will also get the protocol definition, and you can add it into your class..
#interface MyClass <OriginalProtocol,MyExtendedProtocolName>
also, be careful when subclassing NSString, it's a cluster and you may not always get the behaviour you're expecting.
Adam Sharp posted a solution that worked for me.
It involves 3 steps:
Defining the methods you want to add as #optional on a protocol.
Making the objects you want to extend conform to that protocol.
Copying those methods into those objects at runtime.
Check out the link for the full details.

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