将协议添加到超类,这将强制从其继承的其他类实现协议

问题描述 投票:1回答:2

所以我是iOS开发的新手,并且在我的实习中对应用程序进行了一些小的更改,这个实例具有相对较大的Objective-c代码库。我一直在树屋学习(哇,爱他们!),我刚刚学习了协议。目前,它们应该在某些情况下使用,教师使用这个例子。

假设您有一家拥有两种不同类型员工的公司:薪水和每小时(很常见)。现在,他们都将继承一个名为Employee的超级类,并且两者都必须调用一个名为“pay”的函数来支付员工的工资。您如何强制执行这些类来实现该功能?当然,使用协议但这需要您记住将其添加到函数声明中。有没有办法将协议添加到超类“Employee”,然后从该类继承的任何内容都必须遵循该超类的一部分协议。还有另一种方法吗?谢谢!

ios swift inheritance swift-protocols
2个回答
3
投票

你在寻找的是一个抽象的课程。抽象类的目的是作为要继承的具体类的基类,但不能直接实例化抽象类。

如果Employee是一个抽象类,那么任何实际实例化Employee实例的尝试都会被编译器报告为错误。您需要实例化Employee的具体子类,例如SalariedEmployeeHourlyEmployee

Employee类的定义将包括需要calculatePay方法,如果具体子类没有实现该方法,则会再次发生编译时错误。

现在,坏消息。 Objective-C和Swift都不支持抽象类。

您可以通过提供一个方法的实现来提供类似的类,如果它没有被子类覆盖,则抛出异常。这给出了运行时错误而不是编译时错误。

EG

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是基类的一部分还是通过增加协议一致性的扩展分配给基类,结果都是一样的;

  • Employee类需要一个生成某种错误的函数的默认实现
  • 子类未能实现该方法不会导致编译时错误

你可以单独为每个子类分配一个协议,比如Payable,但是由于协议不是基类的一部分,你不能说:

 var employees[Employee]

 for e in employees {
     let pay = e.calculatePay()
 }

您将不得不使用稍微复杂的:

 for e in employees {
     if e is Payable {
         let pay = e.calculatePay()
     }
 }

1
投票

不幸的是,abstract功能尚不支持。一个可能的解决方法是在子类未覆盖此类函数时启动fatalError,这样做:

protocol YourProtocol {
  func pay()
}

class Employee: YourProtocol {
  func pay() {
     fatalError("Must Override")
  }
}

class SubEmployee: Employee {
  func pay() {
     print("stuff here")
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.