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 Void
— that'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.