简体   繁体   English

斯威夫特 - 混合抽象和具体方法

[英]Swift - mixing abstract and concrete methods

Swift has no abstract classes and methods. Swift没有抽象的类和方法。 Instead, it offers protocols. 相反,它提供协议。

That's fine when your classes are either fully abstract or fully concrete. 当你的课程完全抽象或完全具体时,这很好。

But what is the best 'Swift' way to implement an abstract class that also has concrete methods? 但是,实现具有具体方法的抽象类的最佳'Swift'方法是什么?

Pseudo-code example: 伪代码示例:

class Animal {
  abstract makeSound()
  abstract eyeCount()
}

class Mammal : Animal {
  override eyeCount { return 2 } // Let's assume all mammals have hard-coded 2 eyes...

class Cat : Mammal {
  override makeSound { print "Meow!" }
}

class Dog : Mammal {
  override makeSound { print "Woof!" }
}

In Mammal, I do want to implement the concrete method eyeCount() because all mammals have 2 hard-coded eyes (supposedly) and I don't want to re-implement it in dog and cat. 在哺乳动物中,我确实想要实施具体的方法eyeCount()因为所有的哺乳动物都有2个硬编码的眼睛(据说是),我不想在狗和猫中重新实现它。 However, makeSound() should only be implemented for Dog and Cat as mammals have varying voices. 但是, makeSound()只能用于Dog和Cat,因为哺乳动物的声音各不相同。

How would you implement this in Swift? 你会如何在Swift中实现它? Thanks! 谢谢!

I would implement it like this: 我会像这样实现它:

class AbstractAnimal
{
    // Fully abstract method
    func methodThatReturnsSomething() -> String  {
        fatalError("methodThatReturnsSomething() is abstract and must be overriden!");
    }

    func eyeCount() -> Int {
        return 2;
    }
}

fatalError prevents Xcode from complaining that abstract method methodThatReturnsSomething() doesn't actually return anything. fatalError阻止Xcode抱怨抽象方法methodThatReturnsSomething()实际上没有返回任何东西。

You can use Protocol Extensions to get the exact same behavior as with Abstract Classes : Checking if abstract methods are implemented in subclasses at compile time. 您可以使用Protocol Extensions获得与Abstract Classes完全相同的行为:检查抽象方法是否在编译时在子类中实现。

protocol Entity {
  // MARK: - Abstract methods
  func filename() -> String

  // MARK: - Traits
  func saveData(data: NSArray)
}

extension Entity {
  func saveData(data: NSArray) {
      // Do something and call:
      let filename = filename()
  }
}

Now you can implement the Entity protocol on a Subclass and the compiler will force you to implement filename() while the saveData() method is already implemented. 现在,您可以在子类上实现Entity协议,编译器将强制您实现filename()同时已实现saveData()方法。

A common method to do this is to have an abstract class that has concrete methods in it. 执行此操作的常用方法是使用具有其中具体方法的抽象类。 All classes can subclass this abstract class to inherit the concrete methods as well as abstract methods. 所有类都可以继承此抽象类,以继承具体方法和抽象方法。

UIGuestureRecognizer and UIGuestureRecognizerSubclass is a very good example of this. UIGuestureRecognizerUIGuestureRecognizerSubclass就是一个非常好的例子。 Because this is intended for subclassing, this abstract class contains many internal concrete methods as well as subclassable abstract methods for you to implement. 因为这是用于子类化,所以这个抽象类包含许多内部具体方法以及可实现的子类可抽象方法。

This is a common pattern for many Swift and Objective-C projects. 这是许多Swift和Objective-C项目的常见模式。

One way you could do this, as suggested by @BobDickinson in Abstract functions in Swift Language , is the following: 正如@BobDickinson 在Swift语言中的抽象函数中所建议的那样,你可以做到这一点的方法如下:

protocol Animal {
    var eyeCount: Int { get }
    func makeSound()
}

// Note - `Mammal` doesn't conform to `Animal`.
class Mammal {
    let eyeCount = 2
}

// Only `Cat` and `Dog` conform to `Animal`, so only they need to implement `makeSound`.
class Dog: Mammal, Animal {
    func makeSound() {
        println("Woof")
    }
}

class Cat: Mammal, Animal {
    func makeSound() {
        println("Meow")
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM