1
protocol TestProtocol {
    init()
}

class Person: NSObject, TestProtocol {
    required override init() {
        super.init()
    }
}

class Man: Person {

}

class Women: Person {

}

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        let classes: [TestProtocol.Type] = [Person.self, Man.self, Women.self]

        classes.forEach { (type) in
            let obj = type.init()

            print(obj)
        }
    }
}

I try to excute these codes in Xcode10.2, Swift version config to Swift5, I expect to get instances of Person, Man and Women, but the console result is:

<TestSwift5.Person: 0x6000006eb3e0>
<TestSwift5.Person: 0x6000006eb3e0>
<TestSwift5.Person: 0x6000006eb3e0>

which is confuse me, anyone can explain it.

looks forward your answer, thanks.

light_bo
  • 21
  • 3

1 Answers1

2

There are some key differences in subclassing from NSObject vs. native Swift subclasses.

Swift native base class or NSObject

I'm not an expert in exactly why the difference, but it has to do with Objective-C runtime and the additional metadata you get with an NSObject.

In your example, if you do not subclass from NSObject you will see the console output matches what you would expect.

I've run into this problem myself when working with table view and collection view cells. I try to avoid NSObject subclassing when possible, but when it is unavoidable, I also customize the description property from CustomStringConvertible to get what I need.

You can use techniques like Reflection to get the most out of this as well.

protocol TestProtocol {
    init()
}

class Person: TestProtocol {
    required init() {

    }
}

class Man: Person {
    required init() {
        super.init()
    }
}

class Women: Person {

}

When you run these in Xcode or playground you get the following:

__lldb_expr_16.Person
__lldb_expr_16.Man
__lldb_expr_16.Women

Jake
  • 36
  • 4