当前位置: 首页 > 面试题库 >

将Swift协议与泛型一起使用

巫马善
2023-03-14
问题内容

我有一个简单的示例,它似乎应该工作:

import CoreData

@objc protocol CoreDataModel {
    @optional class func entityName() -> String
}

class AbstractModel: NSManagedObject, CoreDataModel {
    class func create<T : CoreDataModel>(context:NSManagedObjectContext) -> T {
        var name = T.entityName?()
        var object = NSEntityDescription.insertNewObjectForEntityForName(name, inManagedObjectContext: context) as T
        return object
    }
}

因此,我们有一个名为的类AbstractModel,它符合协议CoreDataModel,并CoreDataModel定义了一个可选的类方法entityName

但是,这一行:

var name = T.entityName?()

导致错误:

类型名称后的预期成员名称或构造函数调用

知道我在做什么错吗?

编辑

@optional从声明中删除单词并稍微更改函数可以使代码得以编译,但是现在我遇到了运行时错误,指出

“快速动态投放失败”

@objc protocol CoreDataModel {
     class func entityName() -> String
}

class AbstractModel: NSManagedObject, CoreDataModel {

    class func entityName() -> String {
        return "AbstractModel"
    }

    class func create<T : CoreDataModel>(aClass:T.Type, context:NSManagedObjectContext) -> T {
        var name = aClass.entityName()
        var object = NSEntityDescription.insertNewObjectForEntityForName(name, inManagedObjectContext: context) as T
        return object
    }
}

问题答案:

我无法解释为什么您的代码会导致运行时异常。但是,如果您更改函数原型,它将起作用

class func create<T : CoreDataModel>(aClass:T.Type, context:NSManagedObjectContext) -> T

class func create<T : NSManagedObject where T: CoreDataModel>(aClass:T.Type, context:NSManagedObjectContext) -> T

假设您的托管对象子类符合协议,例如

extension Event : CoreDataModel {
    class func entityName() -> String {
        return "Event"
    }
}

然后工作并创建一个新对象:

let newManagedObject = AbstractModel.create(Event.self, context: context)

或者,您可以使用从答案到“Swift:返回类型为self的数组”的方法,并定义NSManagedObjectContext该类的扩展:

extension NSManagedObjectContext {
    func create<T : NSManagedObject where T : CoreDataModel >(entity: T.Type) -> T {
        var classname = entity.entityName()
        var object = NSEntityDescription.insertNewObjectForEntityForName(classname, inManagedObjectContext: self) as T
        return object
    }
}

然后将创建一个新对象

let newManagedObject = context.create(Event.self)


 类似资料:
  • 问题内容: 我在理解Hibernate如何处理泛型时遇到一些麻烦,并且想知道实现我的目标的最佳方法。 给定一个简单的通用实体: 在进行hibernate初始化时,出现异常: 我几乎可以肯定,这是因为我没有给hibernate一些可能的限制条件。我知道你可以指定的东西,如上面的注释,但你失去使用泛型的灵活性。我可以使用注解限制可接受的泛型的范围吗?例如:如果我想要class ,该类从抽象类继承而来,

  • 问题内容: 更新: 感谢所有提供帮助的人-这个答案的答案在于我在更复杂的代码中没有注意到的内容以及对Java5协变量返回类型不了解的内容。 原始帖子: 今天早上我一直在玩一些东西。虽然我知道我 可以用 不同的方式解决整个问题,但我发现自己一直迷恋于弄清楚为什么它没有按我预期的那样工作。在花了一些时间阅读这些内容之后,我发现我离理解还很近,因此我将其作为一个问题来看看我是否只是愚蠢,或者是否真的有我

  • 我正在尝试构建一个通用方法,该方法将调用任何特定于API的endpoint,每个endpoint都返回自己的对象类型。 以上操作不起作用(失败,出现空指针异常) 还尝试了这个: 这失败了: 我已经看到了一种可能的解决方案,通过传入所需类的虚拟对象,但这不是一个理想的选择,因为它需要添加类型参数并向下传递一长串调用。 不知道这将如何工作。

  • 想得到一些建议 我的班级结构是这样的 在我的主代码(MainProg)中,我试图使用相同的函数来引用服务类中的2个方法,并看到注释中的编译错误 有没有办法声明我的函数对象,以便可以使用相同的函数对象来引用采用不同类型参数的方法?

  • 问题内容: 我有一个协议,该协议继承自另一个协议,并且满足扩展要求。 还有另一种协议,其要求()应该为。 现在,如果我尝试使用as ,那么它将无法编译。它说, 推断的类型“地址”(通过匹配要求“ valueForDetail”)无效:不符合“ Validator”。 这种用法非法吗?我们不能像所有的那样用它代替。 下面是我正在尝试的代码。 更新: 提交了一个错误。 问题答案: David已经提到的

  • 协议(Protocols)为方法,属性和其他需求功能提供了蓝图。 它为方法或属性骨架而不是实现。 通过定义类,函数和枚举,可以进一步完成方法和属性的实现。 协议的一致性满足了协议要求的方法或属性。 语法 协议也遵循与类,结构和枚举类似的语法 - 协议在类,结构或枚举类型名称之后声明。 单个和多个协议声明也是可以的。 如果定义了多个协议,则必须用逗号分隔。 当要为超类定义协议时,协议名称应使用逗号跟