简体   繁体   中英

Swift - protocol method signature based on associatedtype

Is it in Swift, like in TypeScript possible to define a struct where the methods depend on the generics?

protocol UseCase {
  associatedtype Request
  associatedtype Response
  func execute(controller: () throws -> Request) async throws -> Response
}

If Request is Void , the protocol should return a different method signature.

func execute() async throws -> Response

I would write a protocol extension with where Request == Void :

extension UseCase where Request == Void {
    func execute() async throws -> Response {
        try await execute {}
    }
}

When Request is Void , you can still call execute(controller:) , but you can also call the parameterless execute() .

When you conform to the protocol, you would need to implement execute(controller:) , but this isn't a big problem, since you can just ignore the parameter.

Your contract would be a lie, violating the Liskov substitution principle . You can get around it with an underscore and a default parameter, but I recommend against it.

Also, I think you want Never , not Voidthat's what Apple does .

struct JuiceCase: UseCase {
  func execute(
    controller _: () throws -> Never = { fatalError() }
  ) async throws -> String {
    "🧃"
  }
}


I'm trying to figure out what Cristik is saying in the comments but don't get it. What I see here is JuiceCase not semantically conforming to UseCase , even though it syntactically does. My interpretation of "substitutability" is that both must be correct—ie saying that JuiceCase is a UseCase is a lie, even though the compiler currently has no mechanism to verify that.

let juiceCase = JuiceCase()
try await juiceCase.execute() // "🧃"
let useCase: some UseCase = juiceCase
try await useCase.execute { fatalError() } // "🧃"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM