我正在尝试参数化类属性employee
的类型。可能是泛型不是解决此问题的正确工具,但希望看到仍然可以使用它们解决此问题。
假设某位员工的类型可以为Clincal
或Administrative
。
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")
答案 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)
问题在于Type
是EmployeeStateController
类型定义的一部分。您无法初始化其类型未知的对象。
一个想法是使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?
}
的协议(就像第一个示例一样)要简单得多。