协议扩展似乎不会在消费者中强制执行变量?

跟你说

protocol Able: class { var v:UIView? { get set } var x:CGFloat { get set } } 

当然,当你使用Able时,

在此处输入图像描述

如果你忘了“v”或“x”……

这是一个错误。 那很好。

这样做:

 class ScreenThing: UIViewController, Able { @IBOutlet var v: UIView? var x: CGFloat = 0.0 } 

一切都很好。 那很棒。

强制您指定“v”和“x”并确实初始化它们。

但。 尝试这个…

 var _H: UInt8 = 0 protocol Able: class { } extension Able where Self:UIViewController { var p:P { get { return objc_getAssociatedObject(self, &_H) as! P } set { objc_setAssociatedObject(self, &_H, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) __setter() } } } 

能够现在有一个属性p。

您可以在Able中的函数中完美地使用p,或者在ScreenThing中的函数中使用p。 那很棒。

然而…..

当你这样做…..

 class ScreenThing: UIViewController, Able { } 

没有收到错误。

你可以忘记初始化“p”(它会崩溃)。

实际上,您不必将“p”指定为变量(因为必须使用“v”和“x”)。

为什么会这样?

这似乎是个大问题。

有什么不同我要做的,让编译器强制执行“p”,就像它当然通常在协议中强制执行变量一样?


另一种看待这个问题的方法:

鉴于上面的代码:

有没有办法强制编译器在消费者类中需要“p”的初始值设定项?

例如。

我试过这个……

 class ScreenThing: UIViewController, Able { var p:P } 

但这不起作用。

(奇怪的是,编译 – 实际上我不知道它到底在做什么!它似乎是与扩展中的p的“不同”p。但无论如何它都不强制需要初始化器。)

简而言之,上面是否有我可以做或添加的内容,这将使编译器强制我初始化伪属性事物,当然,当我在协议中放置属性时通常会这样做,例如“x “或”v“。

  • 也许我必须在协议中添加一些普通的属性(如“pp”),并以某种方式使p与某种方式相关? 只是一个想法。

(脚注 – 请参阅此内容以了解上述协议中所需的“:class”。)


回答我自己的问题:

我上面的困惑是没有什么可以初始化扩展中var p:P (带有get和set代码块)只是两个函数。

没有什么可以初始化的。

例如:在我的额外问题中,我问“如何强制合规的类在唤醒时启动它?” 这毫无意义。 如果有的话,人们可以问:“如何强迫合规class级确保’唤醒时使用这些function’?” – 这与初始化无关。

另请注意,我在计算变量中的特定示例代码恰好(无关地)使用了未初始化的变量 – 导致混淆。

您不必在协议的采用者中实现p ,因为协议扩展已提供实现。 这就是协议扩展。

更简单的例子:

 protocol P {} extension P { func greet() {print("hello")} } class C : P {} C().greet() 

注意,(1)编译,即使C没有声明greet ,(2)它运行即使C不包含greet的实现。 那是因为这是协议扩展的工作。