如何在Swift中创建抽象类

协议,协议扩展,协议一致性

Swift中没有抽象类(就像Objective-C一样)。 最好的选择是使用协议,就像Java接口一样。 然后,借助Swift 2.0,您可以使用协议扩展添加方法实现和计算的属性实现。 唯一的限制是您不能提供成员变量或常量也没有动态分配

怎么运行的

如果您熟悉Objective-C,协议并不是什么新鲜事物。 为了说明此解决方案,以下示例定义了一个具有单实例方法要求的协议:

 协议RandomNumberGenerator {func random()-> Double} 

该协议RandomNumberGenerator ,要求任何符合条件的类型都具有一个称为random的实例方法,该方法在每次调用时都会返回Double值。

这是采用并符合RandomNumberGenerator协议的类的实现。 此类实现称为线性同余生成器的伪随机数生成器算法:

可以扩展协议以将方法,初始化程序,下标和计算属性实现提供给符合类型。 这使您可以定义协议本身的行为,而不是每种类型的单独一致性或全局函数。

例如,可以扩展randomBool()协议以提供randomBool()方法,该方法使用所需的random()方法的结果返回随机的Bool值:

  扩展 RandomNumberGenerator {func randomBool ()-> Bool {return random()> 0.5}} 

通过在协议上创建扩展,所有符合类型的类型都会自动获得此方法的实现,而无需进行任何其他修改。

协议扩展可以将实现添加到符合标准的类型,但不能使协议扩展或从另一个协议继承。 协议继承始终在协议声明本身中指定。

 礼宾员工{ 
var AnnualSalary:Int {get}
}扩展员工{
var biweeklySalary:Int {
返回self.annualSalary / 26
} func logSalary(){
print(“每年$ \(self.annualSalary)或每两周$ \(self.biweeklySalary)”)
}
} struct SoftwareEngineer:员工{
var AnnualSalary:Int func logSalary(){
打印(“覆盖”)
}
} let sarah = SoftwareEngineer(年薪:100000)
sarah.logSalary()//打印:已覆盖
(sarah作为Employee).logSalary()//打印:每年$ 100000或每两周$ 3846

注意,这甚至为结构提供了“抽象类”之类的功能,但是类也可以实现相同的协议。

还要注意,每个实现Employee协议的类或结构都必须再次声明AnnualSalary属性。

最重要的是,请注意没有动态调度 。 在存储为SoftwareEngineer的实例上调用logSalary ,它将调用该方法的重写版本。 在将logSalaryEmployee之后在实例上调用logSalary ,它将调用原始实现(即使实例实际上是一名Software Engineer它也不会动态调度到覆盖的版本。

您可以使用类型转换中描述的isas运算符来检查协议一致性,并转换为特定协议。 检查和转换为协议遵循与检查和转换为类型完全相同的语法:

  • 如果实例符合协议,则is运算符返回true否则返回false
  • as? 向下运算符的版本返回协议类型的可选值,如果实例不符合该协议,则该值为nil
  • as! 向下转换操作符的版本会强制向下转换为协议类型,如果向下转换失败,则会触发运行时错误。

希望你喜欢这个解释。 如有其他疑问,请访问-iOS专家系列或访谈系列

参考文献:

  1. https://docs.swift.org/swift-book/