使用泛型参数化属性类型

时间:2020-04-17 14:26:06

标签: swift generics

我正在尝试参数化类属性employee的类型。可能是泛型不是解决此问题的正确工具,但希望看到仍然可以使用它们解决此问题。

假设某位员工的类型可以为ClincalAdministrative

class EmployeeStateController {
  var employee: Employee<Type>?
}

我想要做的是能够在不知道员工类型的情况下初始化状态控制器。上面的代码将无法编译,因为Type是未知类型。无论如何,如果执行此操作,它将编译:

class EmployeeStateController<Type> {
  var employee: Employee<Type>?
}

但是我不希望这样,因为实例化Type时我不知道EmployeeStateController。也就是说,我希望能够做到这一点:

// view controller 1: does not know the employee type just yet. 
let stateController = EmployeeStateController() // employee remains nil for now

// view controller 2: knows the employee type so it can assign the employee type. 
stateController.employee = Employee<Clinical>(name: "SomeName")

2 个答案:

答案 0 :(得分:2)

您不能那样做。必须在编译时知道所有类型,并且实例化类型后,变量的类型不能更改。

最接近的方法是使Employee成为协议,并在知道类型时分配一个具体的符合类型。

protocol Employee {
    var name: String { get }
    init(name: String)
}

struct Clinical: Employee {
    let name: String

    init(name: String) {
        self.name = name
    }
}

class EmployeeStateController {
  var employee: Employee?
}

// view controller 1: does not know the employee type just yet.
let stateController = EmployeeStateController() // employee remains nil for now

// view controller 2: knows the employee type so it can assign the employee type.
stateController.employee = Clinical(name: "SomeName")

答案 1 :(得分:1)

问题在于TypeEmployeeStateController类型定义的一部分。您无法初始化其类型未知的对象。

一个想法是使Employee遵守某些协议。

protocol EmployeeProtocol {}

struct Employee<Type>: EmployeeProtocol { ... }

然后您可以使用协议来初始化您的类:

class EmployeeStateController {
    var employee: EmployeeProtocol
}

如果您可以对Type进行断言,则可以使用类型擦除来扩展这个想法:

使协议也符合您的类型,并将EmployeeProtocol的{​​{1}}约束到此协议。

Type

创建一个类型擦除的类型(AnyJobDescribable)和一个类型擦除的EmployeeProtocol对象(AnyEmployee),它们可以包装任何符合protocol JobDescribable { var jobDescription: String { get } } // a Self-constrained protocol that refines Type protocol EmployeeProtcool { associatedType Type: JobDescribable var type: Type { get } } struct Employee<Type: JobDescribable>: EmployeeProtocol { var type: Type } 的对象。

EmployeeProtocol

使用单个// Type-erased object that will serve as Type for the type-erased AnyEmployee struct AnyJobDescribable: JobDescribable { let describable: JobDescribable var jobDescription: String { describable.jobDescription } } // AnyEmployee can be initialized by any EmployeProtocol type, including Employee struct AnyEmployee: EmployeeProtocol { var type: AnyJobDescribable private var employee: Any init<SpecializedEmployee: EmployeeProtocol>(employee: SpecializedEmployee) { self.employee = empyloee type = AnyJobDescribable(describable: employee.type) } } 对象,您现在可以创建一个AnyEmployee,而不必知道您要使用的其他Employee对象。

EmployeeStateController

根据您要执行的操作,这可能不值得。使用employee作为没有// Using AnyEmployee, EmployeeStateController can use any type of Employee // (or EmployeeProtocol) without requiring a generic type in its definition class EmployeeStateController { var employee: AnyEmployee? } 的协议(就像第一个示例一样)要简单得多。