我以这种方式定义了抽象 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是否有限?
答案 0 :(得分:3)
T
在编译时必须具有预定义类型。因此,您无法通过返回具有不同T
的不同协调员来使用makeCoordinator()
的实施来选择ResultType
。
在这种情况下,调用者可以选择他想要分配给T
的值,这可能会破坏该功能。例如,以下两个调用完全有效:
let coordinator: BaseCoordinator<Void> = makeCoordinator()
let coordinator: BaseCoordinator<[Int: [String]]> = makeCoordinator()
将[Int: [String]]
用作通用类型是没有意义的,但它仍然是可能的。根据您在函数调用中选择的泛型类型,强制转换可能起作用或不起作用,这就是强制转换可能导致崩溃的原因。
Tom E建议的可选演员表可以修复潜在的崩溃,但仍无法解决此问题。
因此,如果不使用包装类型删除ResultType
到Any
,就不能使用工厂模式,这会破坏泛型的目的。
如果您想要类型安全,则必须为要实例化的BaseCoordinator
的每个子类创建一个工厂方法,或者只是手动调用它们的初始值设定项。
答案 1 :(得分:0)
您可能想要as?
而不是as!
。前者产生一个可选的,i。即如果演员阵容没有成功,结果将为零。通过这种方式,您可以安全地进行投射,而无需强制执行任何操作。