一个 Objective-C 接口可以有多个实现吗?

25

Objective C接口可以有多种实现方式吗?比如我可以有一个接口,但是有两种实现方式,一种使用数组,另一种使用栈等来实现。

如果可以的话,如何调用它/语法是什么?


使用"协议"怎么样?它更接近Java/C#的接口,这正是我想要的。 - user48545
4个回答

30

Objective-C有一个名为Protocol的概念,它是接口的规范。通过Protocols,Objective-C完全支持规范(但不支持实现)的多继承。因此,有点令人困惑的是,@interface语法实际上定义了类(实现),它只支持单一继承,但可以指定多个Protocols的实现或接口规范的实现。最终,这在本质上与Java非常相似。

例如:

@protocol SomeInterface
- (void)interfaceMethod1;
- (void)interfaceMethod2;
@end

@interface SomeClass:NSObject <SomeInterface>
@end 

@interface AnotherClass:NSObject <SomeInterface>
@end 

无论是 SomeClass 还是 AnotherClass 的实例,它们都声称提供了 SomeInterface 协议所需的实现。

Objective-C 是动态类型语言,不需要对象实际指定要发送的消息。换句话说,你可以随意调用任何你想要的 SomeClass 方法,无论它是否在其接口或协议中规定(这未必是一种生产性或积极的做法)。因此,在这种情况下,所有以下方法都可以编译(虽然会有警告),并且运行正常,尽管没有实现的消息/方法基本上是无操作的。Objective-C 有一个相当复杂(非常酷)的处理方法调用/转发的过程,它超出了这个问题的范围。

SomeClass * someObject = [[SomeClass alloc] init;
[someObject someUnspecifiedMethod];  // Compiles with warning - no op
[someObject interfaceMethod1];

如果您希望定义一个可以是任意类 (@interface) 类型,但实现特定接口 (@protocol) 的东西,您可以使用类似这样的方法:

id <SomeInterface> obj;

obj 可以持有 SomeClassAnotherClass 对象。


你说得对... 我回答了一个更加“基础”的问题(并不是 OP 实际上想问的问题)... 重新阅读后,我可以看出 OP 可能正在寻找更符合你的答案 / 抽象工厂 / 类簇。 - rcw3

25

也许你可以尝试使用Cocoa设计模式中的类簇(Class Cluster)。要开始使用,你需要创建一个名为SomeClass的公共类和两个私有子类SomeArrayClassSomeStackClass。当你需要使用栈时,你的公共类构造函数将创建一个SomeStackClass实例,并将其作为SomeClass的公共可用实例返回。


1
这正是你想要使用的模式。 - bbum
使用“协议”怎么样?它更接近于Java/C#的接口,这正是我想要的。 - user48545

20

如果您投票,请给Roman投票--他的答案是第一个,正确的,只是缺少了一个例子。

您在谈论一个类集群。例如,请查看NSString类。

有NSString:

@interface NSString : NSObject

和NSMutableString:

@interface NSMutableString : NSString

这两个类都在核心类的声明中声明了一组非常少的方法。如果您要创建自己的字符串类,只需要实现这些核心方法即可。NSString中实现的所有其他方法都是使用这些核心方法来实现的。同样,可变字符串中的修改方法也是使用在NSMutableString核心中声明的基本方法来实现的。

显然,通过单独实现一个核心方法- (void)replaceCharactersInRange:(NSRange)range withString:(NSString *)aString来实现所有可变性将会非常低效。因此,在运行时,您会注意到您实际上从未拥有过NSString或NSMutableString的实例,而只有子类的实例(实际上,它们并不是真正的子类...但在这个讨论的背景下,它们可能就是子类)。

那些子类——在运行时使用的实现类——覆盖了NSString和NSMutableString的几乎所有方法,以提供高度优化的特定操作实现。

因此,您可以这样做:

@interface MyAbstractClass : NSObject
... declare factory methods here ...
... declare core methods here ...
@end

@interface MyAbstractClass(AdditionalFunctionality)
... declare convenience here ...
@end

然后,在实现中,将所有核心方法实现为@throw @"必须使用子类",并将所有AdditionalFunctionality方法用核心方法来实现。
这可以完全是私有的——甚至不在头文件中:
@interface MyStackClass : MyAbstractClass @end
@implementation MyStackClass …实现核心方法和需要优化的AdditionalFunctionality方法的重写… @end
对于您的其他类型的类,请重复此操作。然后,在MyAbstractClass上实现工厂方法,根据需要返回子类的实例。

3
你的意思是例如这样吗:
@interface MasterViewController : 
  UIViewController <GKPeerPickerControllerDelegate, 
                    GKSessionDelegate,
                    UITextFieldDelegate,
                    UITableViewDelegate,
                    AVAudioRecorderDelegate> {
}

你是指一个文件中有多个 @implementation/@end 块吗? - Tuomas Pelkonen
找到这个是在寻找一种声明多个委托而不需要创建单独的类和实现的方法。这个方法完美地解决了问题。感谢2年后。 - khollenbeck

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接