我知道Swift中没有抽象类和Abstract
关键字。下面的问题就像实现一个抽象属性一样。
为了方便起见,假设有以下三个类:
class SuperClass: NSManagedObject { // the compiler will complain without 'NSManagedObject', and I don't know why.
public let superInt: Int = 1 // use superInt to represent other stored property for SuperClass.
}
class SubClass1: SuperClass {
let subInt1: Int = 2 // use 'subInt1' to represent other stored property for SubClass1.
}
class SubClass2: SuperClass {
let subInt2: Int = 3 // use 'subInt2' to represent other stored property for SubClass2.
}
protocol TestProtocol {
var count: Int { get } // a computed property
func printInt() // a custom method
}
在这里,这些类都是CoreData中定义的对象,特别是超类是一个抽象实体。我想为超类扩展一些接口(上面的
TestProtocol
),以便使用多态性。我想出了两种方法:方法1:让超类确认
TestProtocol
。extension SuperClass: TestProtocol {
var count: Int { return superInt }
func printInt() { print("Here is SuperClass. Count: \(count)") }
}
extension SubClass1 {
override var count: Int { return subInt1 }
override func printInt() { print("Here is SubClass1. Count is \(count)") }
}
extension SubClass2 {
override var count: Int { return subInt2 }
override func printInt() { print("Here is SubClass2. Count is \(count)") }
}
// Here is the test code
let subClasses: [SuperClass] = [SubClass1(), SubClass2()]
subClasses.forEach { $0.printInt() }
方法2:将子类转换为协议对象。
extension SubClass1: TestProtocol {
var count: Int { return subInt1 }
func printInt() { print("Here is SubClass1. Count is \(count)") }
}
extension SubClass2: TestProtocol {
var count: Int { return subInt2 }
func printInt() { print("Here is SubClass1. Count is \(count)") }
}
// Here is the test code
let subClasses: [SuperClass] = [SubClass1(), SubClass2()]
subClasses.forEach { ($0 as! TestProtocol).printInt() }
在方法1中,一切看起来都很好。但我必须在超类中实现代码,这是完全无用的。这种方法似乎有点语法技巧。
在方法2中,所有代码都是有用的,但最后一行的转换破坏了代码的优雅。连续使用
($0 as! TestProtocol).printInt()
这样的代码让我抓狂。两种方法我都不满意。那么,推荐的方法是哪一种呢,还是有更好的方法呢?
最佳答案
在第二种方法中,实际上不需要使用casting(($0 as! TestProtocol).printInt()
)。以下是方法:
let subClasses: [TestProtocol] = [SubClass1(), SubClass2()]
subClasses.forEach { $0.printInt() }
通过将
subClasses
数组键入TestProtocol
而不是SuperClass
可以消除强制转换的需要,因为编译器现在知道subClasses
中的每个元素都符合TestProtocol
并且因此有一个方法printInt()
。