我知道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()

07-27 13:40