如何使用超类中声明的方法返回子类的实例? [复制]

Posted

技术标签:

【中文标题】如何使用超类中声明的方法返回子类的实例? [复制]【英文标题】:How to return instance of subclass with method declared in superclass? [duplicate] 【发布时间】:2018-08-01 13:15:36 【问题描述】:

在 objc 中,我创建了 NSManagedObject 的扩展来创建对象。现在所有子类都可以使用它来创建自己类型的对象。我已经在 swift 中尝试过类似的东西,但正如我所希望的那样,使用泛型。

extension NSManagedObject 

    // MARK: - Creation Methods

    class func create<T: NSManagedObject>(in context: NSManagedObjectContext) -> T 
        let entity = NSEntityDescription.entity(forEntityName: T.description(), in: context)!
        return T(entity: entity, insertInto: context)
    

Person 类是NSManagedObject 的子类中,我可以这样称呼它:

let person = Person.create(context)

person 将是 NSManagedObject 类型,我必须将其转换为 Person,才能访问姓名、电话等属性...

我想以某种方式避免这种情况并让方法 create 返回 instancetype 的排序,但我不确定如何做到这一点?

【问题讨论】:

【参考方案1】:

而不是NSManagedObject 的扩展,我更喜欢协议扩展

protocol Managed

    associatedtype ManagedType: NSManagedObject = Self
    static var entityName : String  get 
    static func create(in context: NSManagedObjectContext) -> ManagedType


extension Managed where Self : NSManagedObject

    static var entityName : String 
        return NSStringFromClass(self).components(separatedBy: ".").last!
    

    static func create(in context: NSManagedObjectContext) -> ManagedType
    
        return NSEntityDescription.insertNewObject(forEntityName: entityName, into: context) as! ManagedType
    

使所有NSManagedObject子类都采用Managed协议

【讨论】:

如果我调用 let person = Person.create(in: context),然后调用 person.name,我得到错误 - 'NSManagedObject' 类型的值没有成员'name' 我更新了答案,提出了一种不同的(有效的)方法。 本质上不是***.com/a/34004264/1187415(针对 Swift 3/4 更新)吗? @MartinR 我检查了你的答案,但那个 unsafeDowncast 看起来不像是最干净的解决方案。我明白你在尝试什么。 IMO 托管协议的解决方案似乎更好。老实说,我有点失望,这不能用泛型更干净地解决 @MegaManX:这个基于协议的解决方案有一个强制转换as! ManagedType,它与unsafeDowncast 一样好或一样坏。请注意,对于重复的问题还有另一个答案 ***.com/a/33583941/1187415,使用自定义初始化程序而不强制转换“技巧”。

以上是关于如何使用超类中声明的方法返回子类的实例? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

在抽象超类的静态方法中创建子类的实例? [复制]

当子类被实例化时,超类的私有成员是不是也被实例化? [复制]

父类中的方法被覆盖以及子类调用父类覆盖的方法

超类中的受保护方法在不同包中的子类中是不是可见? [复制]

超类中子类的C++调用方法?

接口访问权限