Say I have a class Parent and the child is Child1 and Child2.
I declare Parent+ParentCategory and then I declare a method:
-(void) Redraw;
Later I want the Redraw function of Child1 to be different than the Redraw function of Child2.
Can I declare Child1+Child1Category and then override the
-(void) Redraw
Can -(void)Redraw of Child1 call the function in the parent category?
Can that be done?
What would be good approach?
I know classes can inherit each other. I know protocol can extend each other. I wonder why category doesn't?
I do not agree with the given answers:
A.: It is not true, that category's methods win against class' method. This is an implementation detail, but the behavior is not defined.
If the name of a method declared in a category is the same as a method
in the original class, or a method in another category on the same
class (or even a superclass), the behavior is undefined as to which
method implementation is used at runtime.
B.
But this does not matter. You neither define a method in a category that is defined in the class nor define a method in two clashing categories. The cit. simply does not apply to your case. It applies to something like this:
#interface A : NSObject
- (void)doSomething;
#end
#implementation A
- (void)doSomething {}
#end
#interface A (Addition)
- (void)doSomething;
#end
#implementation A (Addition)
- (void)doSomething {}
#end
If I understand you correct, you do not want to do this. You want something like that:
Base level:
#interface A : NSObject
#end
#implementation A
#end
#interface A (Addition)
- (void)doSomething;
#end
#implementation A (Addition)
- (void)doSomething {}
#end
This does not break the rule, because there is no method in the category, which is in the class.
Subclass level:
#interface B : A
#end
#implementation B
#end
#interface B (Addition)
- (void)doSomething;
#end
#implementation B (Addition)
- (void)doSomething {}
#end
There is no clash on the level of B for the same reason as there is no clash on the level of A.
Somebody might say, that there is a clash, because B inherits -doSomething from A. But this is no clash, because in this case a priority rule applies: Subclasses overwrite methods.
You can do that.
Edit:
You can check the problem simply by adding the method to the class. Would that compile? In the clashing case, it wouldn't. In your case, it would.
I will replay with a cit. from this answer:
Lets just put it this way. Don't override methods using categories, period, ever, end of answer.
The reason of this is that while it is exactly known that a category's method always win against a class method (that is, if you implement a method in a category that's already declared in the class you are extending with the category the method of the category will be called.) when you have multiple category implementing the same method which implementation takes precedence is undefined
It is not wise to use category to do this. Categories add methods to the current class. If there are multiple methods with the same name, it will replace the old one (it is NOT an override). But unfortunately it is hard to say which one is replaced. Don't do it or you may get in trouble.
And you probably can not call the method in Parent from the child category. The most proper design here is a protocol.
Related
Here below the definitions of two classes (Foo and Bar) and two respective subclasses (SubFoo and SubBar). Foo is a kind of a dummy class and Bar has a method that takes a Foo instance as a parameter:
#interface Foo
#end
#interface SubFoo : Foo
#end
#interface Bar
- (void)doSthWithFoo:(Foo *)aFoo;
#end
#interface SubBar : Bar
// other methods
#end
Implementations are skipped but consider them being straightforward.
Only then in the implementation of SubBar there is this twist:
#implementation SubBar
- (void)doSthWithFoo:(SubFoo *)aFoo
{
// Do stuff with object of type *SubFoo*
}
// other methods
#end
In the subclass, doSthWithFoo: is overridden and the parameter type is changed to SubFoo – in place of Foo, as in the parent class. This is intentionally done so, as SubBar can only work with SubFoo's so to speak.
This compiles fine, runs fine and does not produce any warnings – kind of surprisingly I must admit. But somehow it doesn't feel very right, even though IMO it's a relatively clean way of doing things..
I am aware that a parameter of type id could be passed instead, but then I'd lose type checking (for Foo) from within Xcode. I am also aware that the same could be accomplished by assigning to id and then to the specific type or by checking and casting – although I haven't tried those options.
Is this a "legitimate" way of doing things? Are there any other alternatives?
I have class A, which exposes a way of getting and setting an object of type Foo. In property parlance, I generally declare this in the interface:
#property (nonatomic, strong) Foo * foo;
This (in modern ObjC) generates both the accessors and an ivar, _foo for storage.
If I want to do custom work in the accessors, I can implement one or both of them myself. But what if I not only want to do custom work, I actually don't want the ivar? In other words, I'm doing something else with the Foo object, like handing it back and forth to another internal object that I'm composed with. I don't actually need to keep storage for foo in the instance of A at all.
It seems like I have two choices:
Declare the property, implement both accessors, and simply ignore the fact that the compiler creates storage for _foo, and never use it.
Declare my accessors explicitly: - (Foo *)foo and - (void)setFoo:(Foo *)foo in the interface, like I used to in pre-modern ObjC.
The first seems inelegant at runtime, and the second seems inelegant in the declaration (where I'd probably now have a mix of properties and property-like accessors).
Is there a way to declare a property and have it serve as purely a declaration?
Use the #dynamic keyword in the implementation file. The usual discussion of #dynamic describes it as not creating the accessors at compile time. Not usually mentioned is that is also has the effect of doing nothing to create storage for the property, which is exactly what is desirable in this case.
#implementation A
#dynamic foo;
- (Foo *)foo
{
// get a Foo from somewhere and return it.
}
- (void)setFoo:(Foo *)foo
{
// do something with foo
}
#end
(Note: answered my own question since I discovered this while writing up the question and it seemed interesting and nonobvious.)
If you override both the setter and getter and don't use the variable within the setter and getter, a variable will not be created.
For example, if you have a class for which you want a firstName and lastName property, but perhaps also a setter and getter for a fullName property, if your fullName setter simply parses a string into firstName and lastName and sets these properties to that (and never stores the full string into a fullName variable), and your fullName getter simply returns the concatenated firstName + lastName and never uses a fullName variable, one will never be created.
This is according to Apple's official documentation. Scroll down to "You Can Implement Custom Accessor Methods"
#dynamic is probably the way to go.
However, there are two other ways you can do this as well:
An Unimplemented Category
You can use an un-implemented category to declare a property, but not get the backing storage:
#interface Foo : NSObject
#end
#interface Foo (UnimplementedProperties)
#property (strong) id bar;
#end
#implementation Foo
#end
By not declaring the implementation of the category (#implementation Foo (UnimplementedProperties)), the properties won't be synthesized.
A Protocol
You can declare the properties on a protocol, and then make your class conform to that protocol. This has the same effect as the unimplemented category: the methods are declared, but the properties are not synthesized.
#protocol FooProperties <NSObject>
#property (strong) id bar;
#end
#interface Foo : NSObject <FooProperties>
#end
When naming parameters in Objective-C, does it matter -that is, it is advisable for documentation / legibility - if I use the same name for similar methods? For example:
#interface Zookeeper : Employee
-(void) washAnimal:(Animal *)someAnimal;
-(void) feedAnimal:(Animal *)someAnimal;
-(void) trainAnimal:(Animal *)someAnimal;
...
Or, should it be like so:
#interface Zookeeper : Employee
-(void) washAnimal:(Animal *)animalToBeWashed;
-(void) feedAnimal:(Animal *)animalToBeFed;
-(void) trainAnimal:(Animal *)animalToBeTrained;
...
Thanks!
In the example you gave, I'd just use animal as the name for all 3. Look at UITableViewDelegate and UITableViewDataSource methods - all arguments for the table view in question are named tableView.
Objective-c class can be extended by categories.
But with multi category extensions on a same class by over define a same method, the result is not defined -- As following case:
#implementation someClass (category1)
- (void)foo {}
#end
#implementation someClass (category2)
- (void)foo {}
#end
In that case, compiler even won't show any warning message. In some big project and with different people for maintenance, this kind of case is quite difficult to be addressed.
So my question is: is there any sophisticated pattern or resolution for avoiding this scenario?
For big projects, a good practice is to also add a prefix to your method names like :
- (void)nd_foo;
- (void)sp_foo;
A class can be extended in Objective C using a category such as:
#interface NSString (CategoryName)
-(NSString *)myFabulousAddition; // a fabulous additional method
#end
/////////////////////////////
#implementation NSString (CategoryName)
-(NSString *)myFabulousAddition {
// do something fabulous...
}
#end
In this small example, I would be adding the method myFabulousAddition to NSString. I could then call it by [anNSString myFabulousAddition] just as if it were part of the NSString set of methods. Great and useful.
In the Apple documents regarding Categories, the docs state:
There’s no limit to the number of
categories that you can add to a
class, but each category name must be
different, and each should declare and
define a different set of methods.
What if you have something like this:
#interface NSString (CategoryName)
-(NSString *)myFabulousAddition; // a fabulous additional method
#end
#interface NSString (ANOTHERCategoryName)
-(NSString *)myFabulousAddition; // a DIFFERENT fabulous additional method
// BUT with same name as the other category
#end
/////////////////////////////
#implementation NSString (CategoryName)
-(NSString *)myFabulousAddition {
// do something fabulous...
}
#end
#implementation NSString (ANOTHERCategoryName)
-(NSString *)myFabulousAddition {
// do something equally fabulous, but DIFFERENT...
}
#end
The lack of a name in the parenthesis indicates that the form is an extension to the class, like so:
#interface MyObject () // No name -- an extension vs category to MyObject
- (void)setNumber:(NSNumber *)newNumber;
#end
Does the category name have any meaning to the compiler or linker? Is the category name part of the method signature in anyway or is it part of a primitive namespace? If the category name is meaningless, how do you know if you are about to stomp on another method and get undefined behavior?
The way to avoid stomping on methods is to prefix your category method names, like this:
#interface NSString (MyCompanyCategoryName)
- (NSString *)MYCO_fabulousAddition;
#end
If you get a collision of method names from different categories, then which one 'wins' at run time is completely undefined.
The name of a category is almost entirely useless, with the exception being that the nameless category (i.e. ()) is reserved for class extensions. Methods from class extensions are supposed to be implemented in the class' main #implementation.
The category name doesn't mean anything special, it's just an identifier. Unless the linker (or runtime loader) decides to give you a warning, there is no way to tell that multiple categories are defining the same method.
The behavior is (largely) unpredictable - one of the categories will win out, but you can't tell which one. Also, I think it's well possible you will start out with one implementation and end up with another one (if the second category is loaded after the first).
It certainly acts as an identifier, from the programmer's point of view. In the compiler point of view category methods are simply added as an extension of the class ( from which it is extending), regardless of the name.
And yes you can add categories of the same class with the same identifiers, even with same functions. But you definitely can't override any function because categories are just part of the class once you define them ( Just like you can't override a function of a class from within that class ).
As they are being added at runtime, they don't raise any error and only at runtime compiler selects the function, which is totally unpredictable.
i believe that they don't have any meaning. You don't really use them in your code ... Since they are categories and ... the semantic of a category ... is just to categorize something, i think this is somewhat logical ...
I would say they just simply gather the methods ...
On the other hand your question is very valid ... You DON'T KNOW if you override a method. If you are in the same project then the compiler issues a warning (or an error ? i don't remember), however if you are overriding a method from a library, then .. you are out of luck ...