将协议添加到 super class,这将强制从它继承的其他 classes 实现协议
Add protocol to super class which will force other classes that inherit from it to implement protocol
所以我是 iOS 开发的新手,在我的实习期间一直致力于对具有相对较大 objective-c 代码库的应用程序进行细微更改。我一直在从 Treehouse 学习 swift(哇,爱他们!),我刚刚了解了协议。目前,它们应该在某些情况下使用,讲师使用了这个例子。
假设您的公司有两种不同类型的员工:工资和小时工(很常见)。现在,他们都将从一个名为 Employee 的超级 class 继承,并且都必须调用一个名为 "pay" 的函数来支付员工工资。您如何强制执行这些 classes 来实现该功能?当然,使用协议,但这需要您记住将其添加到函数声明中。有没有一种方法可以将协议添加到 super class "Employee",然后从 class 继承的任何东西都必须遵循作为 superclass 一部分的协议。还有另一种方法吗?谢谢!
遗憾的是 abstract
函数尚不支持。一种可能的解决方法是在此类函数未被子类覆盖时启动 fatalError
,这样做:
protocol YourProtocol {
func pay()
}
class Employee: YourProtocol {
func pay() {
fatalError("Must Override")
}
}
class SubEmployee: Employee {
func pay() {
print("stuff here")
}
}
您要查找的是 摘要 class。 抽象class的目的是充当基础class以供具体class继承,但抽象class 不能直接实例化。
如果 Employee
是一个抽象 class 那么任何试图实际实例化 Employee
实例的尝试都会被编译器报告为错误。您需要实例化 Employee
的具体子 class,例如 SalariedEmployee
或 HourlyEmployee
。
Employee
class 的定义将包括 calculatePay
方法是必需的,如果具体的子 class 没有,则会再次发生编译时错误实施该方法。
现在,坏消息来了。 Objective-C 和 Swift 都不支持抽象 classes.
您可以通过提供一种方法的实现来提供类似的 class,如果该方法未被子class 覆盖则抛出异常。这给出了运行时错误而不是编译时错误。
例如
class Employee {
var givenName: String
var surname: String
...
init(givenName: String, surname: String) {
self.givenName = givenName
self.surname = surname
}
func calculatePay() -> Float {
fatalError("Subclasses must override calculatePay")
}
}
class SalariedEmployee: Employee {
var salary: Float
init(givenName: String, surname: String, annualSalary: Float) {
salary = annualSalary
super.init(givenName: givenName, surname: surname)
}
override func calculatePay() -> Float {
return salary/12 // Note: No call to super.calculatePay
}
}
无论 calculatePay
是基础 class 的一部分还是通过增加协议一致性的扩展分配给基础 class,结果都是一样的;
Employee
class 将需要生成某种错误的函数的默认实现
- 子class实现方法失败不会导致编译时错误
您可以为每个子 class 单独分配一个协议,例如 Payable
,但是由于该协议不是基础 class 的一部分,您不能说类似于:
var employees[Employee]
for e in employees {
let pay = e.calculatePay()
}
你必须使用稍微复杂一点的:
for e in employees {
if e is Payable {
let pay = e.calculatePay()
}
}
我的方法是将委托作为参数包含在 class 初始值设定项中。请看下面的代码:
protocol ProtocolExample {
func somethingNeedsToHappen()
}
// typical class example with delegate property for the required protocol
class ClassExampleA {
var delegate: ProtocolExample!
init() {
}
func aCriticalMethodWithUpdates() {
delegate.somethingNeedsToHappen()
}
}
// use class example in a view controller. Can easily forget to invoke the delegate and protocol
class MySampleViewControllerA: UIViewController {
var classExampleA : ClassExampleA!
func loadMyData() {
classExampleA = ClassExampleA()
}
}
// an alternative approach for the class is to include the delegate parameter in the initializer.
class ClassExampleB {
var delegate: ProtocolExample!
init(delegateForUpdates: ProtocolExample) {
delegate = delegateForUpdates
}
func doSomething() {
delegate.somethingNeedsToHappen()
}
}
// go to use it and you're reminded that the parameter is required...
class MySampleViewControllerB: UIViewController {
var classExampleB: ClassExampleB!
func loadMyData() {
classExampleB = ClassExampleB() // error: Missing argument for parameter 'delegateForUpdates' in call
}
}
// so to avoid error:
class MySampleViewControllerC: UIViewController {
var classExampleB: ClassExampleB!
func loadMyData() {
classExampleB = ClassExampleB(delegateForUpdates: <#ProtocolExample#>)
}
}
所以我是 iOS 开发的新手,在我的实习期间一直致力于对具有相对较大 objective-c 代码库的应用程序进行细微更改。我一直在从 Treehouse 学习 swift(哇,爱他们!),我刚刚了解了协议。目前,它们应该在某些情况下使用,讲师使用了这个例子。
假设您的公司有两种不同类型的员工:工资和小时工(很常见)。现在,他们都将从一个名为 Employee 的超级 class 继承,并且都必须调用一个名为 "pay" 的函数来支付员工工资。您如何强制执行这些 classes 来实现该功能?当然,使用协议,但这需要您记住将其添加到函数声明中。有没有一种方法可以将协议添加到 super class "Employee",然后从 class 继承的任何东西都必须遵循作为 superclass 一部分的协议。还有另一种方法吗?谢谢!
遗憾的是 abstract
函数尚不支持。一种可能的解决方法是在此类函数未被子类覆盖时启动 fatalError
,这样做:
protocol YourProtocol {
func pay()
}
class Employee: YourProtocol {
func pay() {
fatalError("Must Override")
}
}
class SubEmployee: Employee {
func pay() {
print("stuff here")
}
}
您要查找的是 摘要 class。 抽象class的目的是充当基础class以供具体class继承,但抽象class 不能直接实例化。
如果 Employee
是一个抽象 class 那么任何试图实际实例化 Employee
实例的尝试都会被编译器报告为错误。您需要实例化 Employee
的具体子 class,例如 SalariedEmployee
或 HourlyEmployee
。
Employee
class 的定义将包括 calculatePay
方法是必需的,如果具体的子 class 没有,则会再次发生编译时错误实施该方法。
现在,坏消息来了。 Objective-C 和 Swift 都不支持抽象 classes.
您可以通过提供一种方法的实现来提供类似的 class,如果该方法未被子class 覆盖则抛出异常。这给出了运行时错误而不是编译时错误。
例如
class Employee {
var givenName: String
var surname: String
...
init(givenName: String, surname: String) {
self.givenName = givenName
self.surname = surname
}
func calculatePay() -> Float {
fatalError("Subclasses must override calculatePay")
}
}
class SalariedEmployee: Employee {
var salary: Float
init(givenName: String, surname: String, annualSalary: Float) {
salary = annualSalary
super.init(givenName: givenName, surname: surname)
}
override func calculatePay() -> Float {
return salary/12 // Note: No call to super.calculatePay
}
}
无论 calculatePay
是基础 class 的一部分还是通过增加协议一致性的扩展分配给基础 class,结果都是一样的;
Employee
class 将需要生成某种错误的函数的默认实现- 子class实现方法失败不会导致编译时错误
您可以为每个子 class 单独分配一个协议,例如 Payable
,但是由于该协议不是基础 class 的一部分,您不能说类似于:
var employees[Employee]
for e in employees {
let pay = e.calculatePay()
}
你必须使用稍微复杂一点的:
for e in employees {
if e is Payable {
let pay = e.calculatePay()
}
}
我的方法是将委托作为参数包含在 class 初始值设定项中。请看下面的代码:
protocol ProtocolExample {
func somethingNeedsToHappen()
}
// typical class example with delegate property for the required protocol
class ClassExampleA {
var delegate: ProtocolExample!
init() {
}
func aCriticalMethodWithUpdates() {
delegate.somethingNeedsToHappen()
}
}
// use class example in a view controller. Can easily forget to invoke the delegate and protocol
class MySampleViewControllerA: UIViewController {
var classExampleA : ClassExampleA!
func loadMyData() {
classExampleA = ClassExampleA()
}
}
// an alternative approach for the class is to include the delegate parameter in the initializer.
class ClassExampleB {
var delegate: ProtocolExample!
init(delegateForUpdates: ProtocolExample) {
delegate = delegateForUpdates
}
func doSomething() {
delegate.somethingNeedsToHappen()
}
}
// go to use it and you're reminded that the parameter is required...
class MySampleViewControllerB: UIViewController {
var classExampleB: ClassExampleB!
func loadMyData() {
classExampleB = ClassExampleB() // error: Missing argument for parameter 'delegateForUpdates' in call
}
}
// so to avoid error:
class MySampleViewControllerC: UIViewController {
var classExampleB: ClassExampleB!
func loadMyData() {
classExampleB = ClassExampleB(delegateForUpdates: <#ProtocolExample#>)
}
}