Objective C - 类别和继承 - 将方法添加到base并将覆盖添加到派生类

时间:2022-04-06 22:54:42

I know that categories should not be used to override a method in the class they are extending. However, what about the following scenario.

我知道不应该使用类别来覆盖它们正在扩展的类中的方法。但是,下面的场景呢?

Consider the classes:

考虑这些课程:

Base.h

#import <Foundation/NSObject.h>

@interface Base: NSObject { NSNumber *n; }
@end

Derived.h

#import "Base.h"

@interface Derived: Base { NSString *s; }
@end

With categories:

Base+Serialize.h

#import "Base.h"

@interface Base (Serialize)
- (NSString*)serialize;
@end

Base+Serialize.m

#import "Base+Serialize.h"

@implementation Base (Serialize)
- (NSString*)serialize
{
    return [NSString stringWithFormat:@"%@", n];
}

@end

Derived+Serialize.h

#import "Derived.h"

#import "Base+Serialize.h"

@interface Derived (Serialize)
- (NSString*)serialize;
@end

Derived+Serialize.m

#import "Derived+Serialize.h"

@implementation Derived (Serialize)
- (NSString*)serialize
{
    return [NSString stringWithFormat:@"%@, %@", s, [super serialize]];
}

@end

Obviously, this is a contrived/simplified example. But it works well to demonstrate what I would like to do. Essentially, I want to provide additional functionality to multiple classes in an inheritance hierarchy.

显然,这是一个人为/简化的例子。但它很好地展示了我想做的事情。本质上,我想为继承层次结构中的多个类提供附加功能。

Is this a safe/valid use of categories? Any gotchas?

这是对类别的安全/有效使用吗?任何陷阱?

2 个解决方案

#1


1  

This is an acceptable way to use categories. Categories do actually add the message to the class, so the message will work just like any other message. This includes inheritance.

这是使用类别的可接受方式。类别确实会将消息添加到类中,因此消息将像任何其他消息一样工作。这包括继承。

Perhaps one thing to watch out for is that you can run into name collisions. I don't know how the runtime handles them, but if two categories supply the same message you may have unexpected behavior since the message you expect is not being called. That being said, you may just want a name which is a little more distinctive than serialize, unless of course, you need that name (e.g. you have an informal protocol).

也许需要注意的一点是,你可能遇到名称冲突。我不知道运行时如何处理它们,但如果两个类别提供相同的消息,则可能会出现意外行为,因为您预期的消息未被调用。话虽这么说,你可能只想要一个比序列化更有特色的名字,除非你需要这个名字(例如你有一个非正式的协议)。

#2


1  

This doesn't seem like a very good object model. Base.h and Derived.h seem fine. What about making a Protocol to define the serialize: method, rather than a category? That would be a little cleaner. Base.h would indicate that it would implement the protocol and Derived could override the method as needed.

这似乎不是一个非常好的对象模型。 Base.h和Derived.h看起来很好。如何使用Protocol来定义serialize:方法而不是类别?那会更清洁一些。 Base.h表示它将实现协议,Derived可以根据需要覆盖该方法。

#1


1  

This is an acceptable way to use categories. Categories do actually add the message to the class, so the message will work just like any other message. This includes inheritance.

这是使用类别的可接受方式。类别确实会将消息添加到类中,因此消息将像任何其他消息一样工作。这包括继承。

Perhaps one thing to watch out for is that you can run into name collisions. I don't know how the runtime handles them, but if two categories supply the same message you may have unexpected behavior since the message you expect is not being called. That being said, you may just want a name which is a little more distinctive than serialize, unless of course, you need that name (e.g. you have an informal protocol).

也许需要注意的一点是,你可能遇到名称冲突。我不知道运行时如何处理它们,但如果两个类别提供相同的消息,则可能会出现意外行为,因为您预期的消息未被调用。话虽这么说,你可能只想要一个比序列化更有特色的名字,除非你需要这个名字(例如你有一个非正式的协议)。

#2


1  

This doesn't seem like a very good object model. Base.h and Derived.h seem fine. What about making a Protocol to define the serialize: method, rather than a category? That would be a little cleaner. Base.h would indicate that it would implement the protocol and Derived could override the method as needed.

这似乎不是一个非常好的对象模型。 Base.h和Derived.h看起来很好。如何使用Protocol来定义serialize:方法而不是类别?那会更清洁一些。 Base.h表示它将实现协议,Derived可以根据需要覆盖该方法。