创建返回泛型的工厂方法

时间:2017-08-29 11:50:28

标签: swift generics inheritance factory

我以这种方式定义了抽象 class

class BaseCoordinator<ResultType>

其他类继承自此类,例如

final class AppCoordinator: BaseCoordinator<Void>
final class AuthFlowCoordinator: BaseCoordinator<AuthFlowCoordinationResult>
final class MainFlowCoordinator: BaseCoordinator<Void>

现在我想创建一个工厂方法。我猜它的样子应该是这样的:

func makeCoordinator<T>() -> BaseCoordinator<T>

但是,当然,我得到的错误就像这样:

Cannot convert return expression of type 'AppCoordinator' to return type 'BaseCoordinator<T>'

Xcode建议我添加as! BaseCoordinator<T>,但我讨厌这种力量向下转换(并且返回?也不满足我,因为我100%肯定我会有一个正确的默认对象),因为我希望保证至少将返回默认Coordinator
感觉我错过了什么,但我真的不知道它是什么。实际上是否可以制作这样的工厂方法,或者Swift generics是否有限?

2 个答案:

答案 0 :(得分:3)

T在编译时必须具有预定义类型。因此,您无法通过返回具有不同T的不同协调员来使用makeCoordinator()的实施来选择ResultType

在这种情况下,调用者可以选择他想要分配给T的值,这可能会破坏该功能。例如,以下两个调用完全有效:

let coordinator: BaseCoordinator<Void> = makeCoordinator()
let coordinator: BaseCoordinator<[Int: [String]]> = makeCoordinator()

[Int: [String]]用作通用类型是没有意义的,但它仍然是可能的。根据您在函数调用中选择的泛型类型,强制转换可能起作用或不起作用,这就是强制转换可能导致崩溃的原因。

Tom E建议的可选演员表可以修复潜在的崩溃,但仍无法解决此问题。

因此,如果不使用包装类型删除ResultTypeAny,就不能使用工厂模式,这会破坏泛型的目的。

如果您想要类型安全,则必须为要实例化的BaseCoordinator的每个子类创建一个工厂方法,或者只是手动调用它们的初始值设定项。

答案 1 :(得分:0)

您可能想要as?而不是as!。前者产生一个可选的,i。即如果演员阵容没有成功,结果将为零。通过这种方式,您可以安全地进行投射,而无需强制执行任何操作。