Objective c iOS子类化和强制方法

Objective c iOS子类化和强制方法,objective-c,ios,inheritance,methods,enforcement,Objective C,Ios,Inheritance,Methods,Enforcement,我有一个基本视图控制器,它是许多其他视图控制器的子类。有没有一种方法可以强制某些必须在子类中重写的方法 为了安全起见,这比什么都重要 Cheers在其他语言中,这是使用抽象类和方法完成的。在Objective-C中没有这样的东西 最接近的方法是在超类中引发异常,以便子类“被迫”重写它们 [NSException raise:NSInternalInconsistencyException format:@"Subclasses must override %@", NSStringFromSel

我有一个基本视图控制器,它是许多其他视图控制器的子类。有没有一种方法可以强制某些必须在子类中重写的方法

为了安全起见,这比什么都重要


Cheers

在其他语言中,这是使用抽象类和方法完成的。在Objective-C中没有这样的东西

最接近的方法是在超类中引发异常,以便子类“被迫”重写它们

[NSException raise:NSInternalInconsistencyException format:@"Subclasses must override %@", NSStringFromSelector(_cmd)];
在Xcode(使用叮当声等)中,我喜欢使用
\uuuuu属性(不可用(…))
来标记抽象类,这样如果您尝试使用它,就会得到一个错误/警告

它提供了一些保护,防止意外使用该方法

例子 在基类
@interface
中标记“abstract”方法:

进一步,我创建了一个宏:

#define UnavailableMacro(msg) __attribute__((unavailable(msg)))
这允许您执行以下操作:

- (void)myAbstractMethod:(id)param1 UnavailableMacro("You should always override this");

正如我所说,这不是真正的编译器保护,但它与不支持抽象方法的语言一样好。

受rjstelling的启发,我以一种更令人满意的方式解决了这个问题:

在前缀中,定义:

#define abstract __attribute__((unavailable("abstract method")))
然后可以按如下方式添加抽象方法:

- (void) getDataIdentifier abstract;
NS_PROTOCOL_REQUIRES_EXPLICIT_IMPLEMENTATION
@protocol Protocol
@property (readonly) id theWorstOfTimes; // expected-note {{property declared here}} 
@end

// In this example, ClassA adopts the protocol.
@interface ClassA : NSObject <Protocol>
@property (readonly) id theWorstOfTimes;
@end

@implementation ClassA
- (id)theWorstOfTimes{
    return nil; // default implementation does nothing
}
@end

// This class subclasses ClassA (which also adopts 'Protocol').
@interface ClassB : ClassA <Protocol>
@end

@implementation ClassB // expected-warning {{property 'theWorstOfTimes' requires method 'theWorstOfTimes' to be defined - use @synthesize, @dynamic or provide a method implementation in this class implementation}} 
@end
尝试调用此方法将导致编译器语义问题/错误(Xcode 5.1):

更新:
调用该方法(至少不是从类层次结构中调用)似乎不起作用。如果我能解决这个问题,我会带着更新回来

通过使用LLVM功能,您可以要求子类在编译时实现属性(有关为什么不实现方法,请参见下文),如下所示:

- (void) getDataIdentifier abstract;
NS_PROTOCOL_REQUIRES_EXPLICIT_IMPLEMENTATION
@protocol Protocol
@property (readonly) id theWorstOfTimes; // expected-note {{property declared here}} 
@end

// In this example, ClassA adopts the protocol.
@interface ClassA : NSObject <Protocol>
@property (readonly) id theWorstOfTimes;
@end

@implementation ClassA
- (id)theWorstOfTimes{
    return nil; // default implementation does nothing
}
@end

// This class subclasses ClassA (which also adopts 'Protocol').
@interface ClassB : ClassA <Protocol>
@end

@implementation ClassB // expected-warning {{property 'theWorstOfTimes' requires method 'theWorstOfTimes' to be defined - use @synthesize, @dynamic or provide a method implementation in this class implementation}} 
@end
NS\u协议\u需要\u显式\u实现
@协议
@属性(只读)id theWorstOfTimes;//应为注释{{此处声明的属性}
@结束
//在本例中,ClassA采用协议。
@接口ClassA:NSObject
@属性(只读)id theWorstOfTimes;
@结束
@实现类A
-(id)最短时间{
return nil;//默认实现不执行任何操作
}
@结束
//这个类是ClassA的子类(它也采用“协议”)。
@接口ClassB:ClassA
@结束
@实现类B//预期警告{{属性'theWorstOfTimes'需要定义方法'theWorstOfTimes'-使用@synthesis、@dynamic或在此类实现中提供方法实现}
@结束
正如您所看到的,当ClassB重新实现协议时,它会显示属性方法丢失的
预期警告<代码>NS\U协议\u需要\u显式\u实现
只是
属性\u((objc\u协议\u需要\u显式\u实现))的宏
,此代码示例从该功能的测试线束中修改

这过去也适用于方法,但2014年通过a引入了一个bug,现在它只适用于属性,我给作者发了电子邮件让他们知道,所以希望它能回到原来的样子。为了测试bug,您可以向协议中添加一个方法,您将看到ClassB中没有警告。希望您可以将一些方法更改为只读属性,以便至少从中获得一些使用

下面是一些关于
NS\u协议\u需要显式\u实现的文档

答案因语言而异。你在用什么语言?哦,对不起,我改了标题。在Agree的iOS(Objective-C)可能的副本中,值得一提的是,设计良好的“抽象类替代方案”不应要求在导致异常的子类上实现方法,相反,应该在文档中清楚地提到它,或者任何类型的类所需的初始值设定项都可以执行检查修改
NSError
参数。您可能需要NSAssert(否,@“需要实现此方法”)默认情况下,NSAsExt被禁用以释放目标。因此,在不可能的情况下,一个未实现的方法滑入生产中,它不会崩溃App。您也可以考虑使用一个使用“协议”的必要方法。现在,如果您想要某种限制但不花费太多,这是一个很好的解决方案。h重新设计类。如果您得到的不可用属性的参数不是字符串文字,请使用以下命令:
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu