Objective-C - 子类中委托的子类

时间:2012-01-13 11:54:58

标签: iphone objective-c ios oop delegates

这是一个相当复杂的继承层次结构,所以忍受我(我试图简化事情,而不是陈述我使用的确切情况,这更复杂): -

假设我创建了一个UITextField的子类TextField,这是我自己的自定义增强型通用文本字段。现在,为了提供此增强功能,我在init的{​​{1}}方法中设置TextField,以便将super.delegate = self中的所有委托方法发送到{{1} }}。 UITextField实现TextField协议,并接收这些委托方法来做一些有趣的事情。

但是,反过来,我想让TextField拥有拥有委托。所以我创建了一个名为UITextFieldDelegate的新协议(注意缺少TextField - 前缀!)并给TextFieldDelegate一个带有相应属性的ivar UI,以便其他类可以接收委托来自TextField的方法。

我希望你还和我在一起,因为到目前为止我还没有做过任何太复杂的事情。但是让我们说现在,我创建另一个id<TextFieldDelegate> __weak delegate的自定义子类,让我们称之为TextField(在现实生活中,人们可能不需要创建一个子类来实现密码功能,但是让我们假设有一些相当复杂的实现需要这个。)

我们还假设我想要使TextField(类似PasswordTextField具有委托属性)能够发送一组增强的委托方法。例如,也许它可以发送方法PasswordTextField,一旦密码达到所需的复杂程度,就会发送该方法。现在,由于常规TextField中找不到此行为,我创建了一个新协议:passwordIsSecure,它为TextField 定义新的委托方法继承PasswordTextFieldDelegate <TextFieldDelegate>发送的所有委托方法。

问题是:如何在PasswordTextField中实现此功能?不起作用的事情:

继承

我不能简单地从TextField继承委托,因为PasswordTextField的委托只符合TextField而不是TextField,因此我无法发送TextFieldDelegate之类的方法{1}}因为PasswordTextFieldDelegate没有这样的方法。

覆盖ivar

我可以尝试在名为[delegate passwordIsSecure]的委托中声明一个ivar,但编译器抱怨这是一个重复的声明,因为当然在超类中已经有一个名为delegate的ivar,所以这也不起作用*

修改超类

我可以回到TextFieldDelegate类并重新定义代理以实现PasswordTextField TextField,但这看起来很混乱,并告诉{{1它可以发送TextFieldDelegate方法,当然,它不能!

我没有尝试过这个,只是因为它似乎打破了书中所有合理的编码规则。

总之,必须有一些方法可以做到这一点,这样一个类的子类可以拥有它自己的委托,它是超类委托的子委托,并且所有这些都可以很好地融合在一起,但我只能'搞清楚!有什么想法吗?

(*作为一个副作用,我不明白为什么编译器会在PasswordTextFieldDelegate声明一个名为“委托”的“重复”ivar时抱怨,但是当TextField声明一个名为delegate的ivar时不会抱怨这可能是PasswordTextFieldDelegate属性的副本,称为委托!)

3 个答案:

答案 0 :(得分:1)

UITextField委托ivar名为_delegate,而不是委托。因此,为什么你在TextField中再次声明它,而不是在PasswordTextField中。

至于你的委托继承问题。我不确定ObjectiveC是否支持你想要的东西。

您可能只需要输入您的委托'id',而不是'id&lt; TextFieldDelegate&gt;'。然后你可以覆盖setDelegate并确保委托传递conformsToProtocol。但是,您将丢失此处的编译时检查,并且仅对conformsToProtocol

进行运行时检查

答案 1 :(得分:1)

所以,那里!工作..并设法有编译时警告..

SimpleParent.h

@protocol Parentprotocol <NSObject>

@end

@interface SimpleParent : NSObject {
    id<Parentprotocol> obj;
}

@property (retain) id<Parentprotocol> obj;

@end

SimpleParent.m

#import "SimpleParent.h"

@implementation SimpleParent
@synthesize obj;

@end

SimpleChild.h

#import <Foundation/Foundation.h>
#import "SimpleParent.h"

@protocol SimpleChildProtocol <Parentprotocol>


@end

@interface SimpleChild : NSObject

@property (assign) id<SimpleChildProtocol> obj;

@end

SimpleChild.m

#import "SimpleChild.h"

@implementation SimpleChild
@synthesize obj;

@end

答案 2 :(得分:1)

这是一个相当令人困惑的问题,所以请原谅我,如果我错过了这一点,但看起来你的三个不同的继承级别每个都有不同的委托要求,每个代表都必须遵循不同的协议,那么将每个级别的委托作为一个不同名称的ivar,并作为一个不同的参考,它会是一个解决方案吗?

例如,您的基类将具有其delegate,您已决定将其分配给第一个继承子类。这有自己的委托,名为level1delegate,而下一个级别有另一个委托,名为level2delegate。如果该对象符合所有三个协议,您当然可以将所有这三个设置为同一个对象。

基本上,没有规则说委托必须被称为“委托”,所以不要因为不打破它而撕裂自己。