定义具体的关联类型,但我仍然不能将协议用作变量

Defining concrete associatedtype but I still can't use protocol as variable

我想使用 SendMessageUseCase 作为变量类型,例如 var sendMessageUseCase: SendMessageUseCase 但我不能。

我一直收到错误 Protocol 'SendMessageUseCase' can only be used as a generic constraint because it has Self or associated type requirements

这显然是我理解的错误,但它没有意义。

SendMessageUseCase 中,我使用 Where 子句定义了我的关联类型,这意味着从技术上讲,编译器应该能够推断,因为我已经明确定义了 InputOutput 分别为 SendMessageUseCaseInputSendMessageUseCaseOutput

protocol UseCaseInput {}
protocol UseCaseOutput {}
protocol UseCase : AnyObject {
    associatedtype Input: UseCaseInput
    associatedtype Output: UseCaseOutput
    
    func execute(input: Input, _ completion: (_ output: Output) -> ())
}

struct SendMessageUseCaseInput : UseCaseInput {
    var text: String
}

struct SendMessageUseCaseOutput: UseCaseOutput {
    var response: String
}

protocol SendMessageUseCase: UseCase where Input == SendMessageUseCaseInput, Output == SendMessageUseCaseOutput {
    
}

final class TestSendMessageUseCase : SendMessageUseCase {
    func execute(input: SendMessageUseCaseInput, _ completion: () -> ()) {
        
    }
}

// Why this doesn't work?
var sendMessageUseCase: SendMessageUseCase = TestSendMessageUseCase()

SendMessageUseCase.Input 可以是除 SendMessageUseCaseInput 之外的任何其他内容吗?我不这么认为,这就是为什么我认为它应该被推断出来。但显然我错了,无法理解为什么。

感谢@Jessy 的评论,我找到了一个临时解决方案。

some 添加到 sendMessageUseCase 变量将允许我们使用 opaque 类型,但仍然存在限制,因为您不能拥有数组。

有一些会谈来实现这一点,但截至目前(2022 年 5 月 28 日)它仍未实现。

protocol UseCaseInput {}
protocol UseCaseOutput {}
protocol UseCase : AnyObject {
    associatedtype Input: UseCaseInput
    associatedtype Output: UseCaseOutput
    
    func execute(input: Input, _ completion: (_ output: Output) -> ())
}

struct SendMessageUseCaseInput : UseCaseInput {
    var text: String
}

struct SendMessageUseCaseOutput: UseCaseOutput {
    var response: String
}

protocol SendMessageUseCase: UseCase where Input == SendMessageUseCaseInput, Output == SendMessageUseCaseOutput {
}

final class TestSendMessageUseCase : SendMessageUseCase {
    func execute(input: SendMessageUseCaseInput, _ completion: (SendMessageUseCaseOutput) -> ()) {
        
    }
    
}

var sendMessageUseCase: some SendMessageUseCase = TestSendMessageUseCase()

如果有人感兴趣,请查看论坛主题

Lifting the “Self or associated type” constraint on existentials

[[Sema]AST][WIP] Support existentials with concrete assoc. types #21576 (PR已关闭)