Protocol associatedType and
Defined associated type makes classes which conform protocol strong typed. This provide compile-time error handling.
In other hand, generic type makes classes which conform protocol more flexible.
For example:
protocol AssociatedRepository {
associatedtype T
func add(data : T) -> Bool
}
protocol GenericRepository {
func add<T>(data : T) -> Bool
}
class A: GenericRepository {
func add<T>(data : T) -> Bool {
return true
}
}
class B: AssociatedRepository {
typealias T = UIViewController
func add(data : T) -> Bool {
return true
}
}
class A
could put any class into add(data:)
function, so you need to makes your sure that function handle all cases.
A().add(data: UIView())
A().add(data: UIViewController())
both would be valid
But for class B
you will get compile-time error when you will try to put anything except UIViewController
B().add(data: UIView()) // compile-time error here
B().add(data: UIViewController())
protocol associated type typealias assignment compile error
In this case the assignment of Int
to the typealias
is equal to no assignment because it gets overridden by your conforming type:
// this declaration is equal since you HAVE TO provide the type for SomeType
protocol SomeProtocol {
typealias SomeType
func someFunc(someVar: SomeType)
}
Such an assignment provides a default type for SomeType
which gets overridden by your implementation in SomeClass
, but it is especially useful for protocol extensions:
protocol Returnable {
typealias T = Int // T is by default of type Int
func returnValue(value: T) -> T
}
extension Returnable {
func returnValue(value: T) -> T {
return value
}
}
struct AStruct: Returnable {}
AStruct().returnValue(3) // default signature: Int -> Int
You get the function for free only by conforming to the protocol without specifying the type of T
. If you want to set your own type write typealias T = String // or any other type
in the struct body.
Some additional notes about the provided code example
You solved the problem because you made it explicit which type the parameter has. Swift also infers your used type:
class SomeClass: SomeProtocol {
func someFunc(someVar: Double) {
print(someVar)
}
}
So SomeType
of the protocol is inferred to be Double
.
Another example where you can see that SomeType
in the class declaration doesn't refer to to the protocol:
class SomeClass: SomeProtocol {
typealias Some = Int
func someFunc(someVar: Some) {
print(someVar)
}
}
// check the type of SomeType of the protocol
// dynamicType returns the current type and SomeType is a property of it
SomeClass().dynamicType.SomeType.self // Int.Type
// SomeType gets inferred form the function signature
However if you do something like that:
protocol SomeProtocol {
typealias SomeType: SomeProtocol
func someFunc(someVar: SomeType)
}
SomeType
has to be of type SomeProtocol
which can be used for more explicit abstraction and more static code whereas this:
protocol SomeProtocol {
func someFunc(someVar: SomeProtocol)
}
would be dynamically dispatched.
Unable to use associatedType as method returnType in swift as compiler throws Ambiguous inference of associated type
Using an opaque return type (i.e. some
) is not required for what you want to do. When you go to implement the Office
protocol, just return the actual type from the function and computed property you specified and the compiler will infer the associatedtype
for you:
protocol DummyOffice {}
struct EmptyOffice: DummyOffice {}
protocol Office {
associatedtype SubBranch: DummyOffice
var subBranch: SubBranch { get }
func getSubBranch() -> SubBranch
}
struct Apple: Office {
let emptyOffice = EmptyOffice()
func getSubBranch() -> EmptyOffice {
return EmptyOffice()
}
var subBranch: EmptyOffice {
return EmptyOffice()
}
}
How to use a protocol with associative type as return value in Swift?
Not clear what you are trying to achieve, but imho the error stems from the fact that in your addArg
function you define a generic type OP
which should be typically used in the function's arguments and body.
Instead you return a non generic type trying to force it to be treated as a generic `OP.
A quick fix could be a force cast to OP
of your return object:
return OpWithOneArgImpl() as !OP
but I wouldn't recommend it.
In your example your addArg
will always return a OpWithOneArgImpl
thus it could just be defined as a func addArg(arg: Int) -> OpWithOneArgImpl
Hope this helps.
EDIT:
Probably this is not what you're trying to achieve, but hope it can help
with a clearer explanation of what I intended above.
protocol OpWithOneArg {
typealias ArgType
func addAnotherArg(arg: ArgType)
init() // Must have a init with no argument
}
class OpWithOneArgImpl : OpWithOneArg {
typealias ArgType = Int
func addAnotherArg(arg: Int) {
// ...
}
required init() {
// init implementation
}
}
class OpWithNoArg {
func addArgWithOPType<OP: OpWithOneArg where OP.ArgType == Int>(op: OP.Type, arg: Int) -> OP {
return OP() // Here we use the init
}
}
let foo = OpWithNoArg()
foo.addArgWithOPType(OpWithOneArgImpl.self, arg: 3)
Edit:
Maybe you might investigate the use of generic types:
protocol OpWithOneArg {
typealias ArgType
func addAnotherArg(arg: ArgType)
init() // Must have a init with no argument
}
class OpWithOneArgImpl<T> : OpWithOneArg { // Generic implementation confirming to protocol
typealias ArgType = T
func addAnotherArg(arg: T) {
// ...
}
required init() {
// init implementation
}
}
class OpWithNoArg {
func addArgWithOPType<OP: OpWithOneArg>(op: OP.Type, arg: OP.ArgType) -> OP {
return OP() // Here we use the init
}
}
let foo = OpWithNoArg()
// OpWithOneArgImpl<Int>
foo.addArgWithOPType(OpWithOneArgImpl.self, arg: 3)
// OpWithOneArgImpl<String>
foo.addArgWithOPType(OpWithOneArgImpl.self, arg: "Hello")
Related Topics
Ambiguous Use of Operator '-' in Swift with 'Abs()'
Overriding Generic Function Error in Swift
How to Add Document with Custom Id to Firebase (Firestore) on Swift
Google Sign-In via Firebase: Gidsignindelegate Does Not Conform to Viewcontroller
How to Restore Window Position in an Osx Application
Passing Dynamic Int Variable from One Class to Another Class in Swift
Gmail API: How to Send Attachments to The Drafts on Swift
Convert String to Staticstring
Mfmailcomposeviewcontroller Error [Mc] Filtering Mail Sheet Accounts for Bundle Id
How to Unwrap Arbitrarily Deeply Nested Optionals in Swift
Avplayerviewcontroller Black Screen When Swiping on iOS 11
Applewatch Messages Url Works Hard Coded But Not with Variables
Why Specializing a Generic Function Explicitly Is Not Allowed
Dictionary of String:Any Does Not Conform to Protocol 'Decodable'