Swift - 混合抽象和具体方法
Swift - mixing abstract and concrete methods
Swift 没有抽象的 classes 和方法。相反,它提供协议。
当您的 class 完全抽象或完全具体时,这很好。
但是什么是最好的 'Swift' 实现抽象 class 也有具体方法的方法?
伪代码示例:
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!" }
}
在哺乳动物中,我确实想实现具体方法 eyeCount()
,因为所有哺乳动物都有 2 只硬编码的眼睛(据说),我不想在狗和猫中重新实现它。但是,makeSound()
应该只对狗和猫实施,因为哺乳动物有不同的声音。
您将如何在 Swift 中实现它?谢谢!
执行此操作的常用方法是创建一个包含具体方法的抽象 class。所有 classes 都可以子class 这个抽象 class 来继承具体方法和抽象方法。
UIGuestureRecognizer
和 UIGuestureRecognizerSubclass
就是一个很好的例子。因为这是为 subclassing 而设计的,所以这个抽象 class 包含许多内部具体方法以及 subclassable 抽象方法供您实现。
这是许多 Swift 和 Objective-C 项目的常见模式。
正如@BobDickinson 在 Abstract functions in Swift Language 中所建议的那样,您可以这样做的一种方法如下:
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")
}
}
我会这样实现:
class AbstractAnimal
{
// Fully abstract method
func methodThatReturnsSomething() -> String {
fatalError("methodThatReturnsSomething() is abstract and must be overriden!");
}
func eyeCount() -> Int {
return 2;
}
}
fatalError
阻止 Xcode 抱怨抽象方法 methodThatReturnsSomething()
实际上 return 什么都没有。
您可以使用 Protocol Extensions 获得与 Abstract 类 完全相同的行为:检查抽象方法是否是在编译时在子类中实现。
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()
}
}
现在您可以在 子类 上实现 Entity
协议,编译器将强制您实现 filename()
而 saveData()
方法已经实施了。
Swift 没有抽象的 classes 和方法。相反,它提供协议。
当您的 class 完全抽象或完全具体时,这很好。
但是什么是最好的 'Swift' 实现抽象 class 也有具体方法的方法?
伪代码示例:
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!" }
}
在哺乳动物中,我确实想实现具体方法 eyeCount()
,因为所有哺乳动物都有 2 只硬编码的眼睛(据说),我不想在狗和猫中重新实现它。但是,makeSound()
应该只对狗和猫实施,因为哺乳动物有不同的声音。
您将如何在 Swift 中实现它?谢谢!
执行此操作的常用方法是创建一个包含具体方法的抽象 class。所有 classes 都可以子class 这个抽象 class 来继承具体方法和抽象方法。
UIGuestureRecognizer
和 UIGuestureRecognizerSubclass
就是一个很好的例子。因为这是为 subclassing 而设计的,所以这个抽象 class 包含许多内部具体方法以及 subclassable 抽象方法供您实现。
这是许多 Swift 和 Objective-C 项目的常见模式。
正如@BobDickinson 在 Abstract functions in Swift Language 中所建议的那样,您可以这样做的一种方法如下:
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")
}
}
我会这样实现:
class AbstractAnimal
{
// Fully abstract method
func methodThatReturnsSomething() -> String {
fatalError("methodThatReturnsSomething() is abstract and must be overriden!");
}
func eyeCount() -> Int {
return 2;
}
}
fatalError
阻止 Xcode 抱怨抽象方法 methodThatReturnsSomething()
实际上 return 什么都没有。
您可以使用 Protocol Extensions 获得与 Abstract 类 完全相同的行为:检查抽象方法是否是在编译时在子类中实现。
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()
}
}
现在您可以在 子类 上实现 Entity
协议,编译器将强制您实现 filename()
而 saveData()
方法已经实施了。