I have a protocol
protocol doSomethingProtocol {
associatedtype someType
}
then i have class that is implementing this protocol
class doSomethingClass : doSomethingProtocol {
typealias someType = Int
}
Now i want to use this protocol as a reference in some other class
class someClass : ObservableObject {
private var reference : doSomethingProtocol
}
Now i cannot do this as doSomethingProtocol
has an associatedtype. So i decide to use some
class someClass : ObservableObject {
private var reference : some doSomethingProtocol
init(){
reference = doSomethingClass()
}
}
However this doesn't work. I get the error Property declares an opaque return type, but has no initializer expression from which to infer an underlying type
. Why ? I am giving it initializer expression in the class init.
However when i do something like this
class someClass : ObservableObject {
private var reference : some doSomethingProtocol = doSomethingClass()
init(){}
}
I get no error messages and it compiles. Why, what is the difference between the two.
This is where you went wrong. Opaque (
some
) types solve a completely different problem than protocols with associated types. An opaque type is concrete. It is one, specific type, known at compile time, returned by a function. It just is not known to the caller of the function. It is completely known to the compiler.Given this information, what concrete type is
reference
? It's not known. It's hinted at by the behavior ofinit
, but it's not known to always be that. (Even more so since this is a class that could override itsinit
and assign some other type.)What you're trying to do is done this way:
This defines SomeType == DoSomethingClass, and allows DoSomethingClass to conform to DoSomethingProtocol.
If you're trying to avoid nailing down the type that DoSomethingClass uses here, that's not possible. To conform to a protocol with an associated type, you must provide a concrete type that can be determined at compile time.
Given the problems your running into, I suspect that DoSomethingClass is incorrectly designed, and you don't really want a PAT (protocol with associated type) here. You probably want a generic, or composition, or possibly closures. It is possible (though unlikely) that you want a type eraser. But you don't want opaque types.
(Please capitalize your types. Having leading lowercase for a type is very confusing in Swift.)