Protocol Type Typealias Assignment of Compilation Error

The following code:

protocol SomeProtocol { typealias SomeType = Int // used typealias-assignment func someFunc(someVar: SomeType) } class SomeClass: SomeProtocol { func someFunc(someVar: SomeType) { print(someVar) } } 

gives a compile-time error:

Using the Undeclared Type "SomeType"

Adding, say typealias SomeType = Double , to SomeClass fixes the error.

The question is, what is the type of -attribute-assignment type (which is an optional cue ball) of an associated type protocol declaration, though?

+7
swift swift2 protocols
source share
3 answers

In this case, assigning Int to the typealias value typealias not equal to the assignment because it is overridden by your corresponding type:

 // this declaration is equal since you HAVE TO provide the type for SomeType protocol SomeProtocol { typealias SomeType func someFunc(someVar: SomeType) } 

This assignment provides a default type for SomeType , which is overridden by your implementation in SomeClass , but 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 this feature for free only according to the protocol without specifying type T If you want to set your own type, write typealias T = String // or any other type in the body of the structure.

Some additional notes on the given code example

You solved the problem because you made it explicit, what type the parameter is. Swift also uses your used type:

 class SomeClass: SomeProtocol { func someFunc(someVar: Double) { print(someVar) } } 

So, SomeType protocol is defined as Double .

Another example where you can see that SomeType in the class declaration is not protocol related:

 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 this:

 protocol SomeProtocol { typealias SomeType: SomeProtocol func someFunc(someVar: SomeType) } 

SomeType must be of type SomeProtocol , which can be used for more explicit abstraction and more static code, whereas this:

 protocol SomeProtocol { func someFunc(someVar: SomeProtocol) } 

will be dynamically sent.

+5
source share

The documentation for related types contains some information in the protocols.

Their use abounds in the entire standard library, the SequenceType protocol, which declares typealias for Generator (and indicates that it matches GeneratorType ), is referenced as an example. This allows the protocol declaration to refer to these aliases.

In your case, when you used typealias SomeType = Int , you probably meant that "I want SomeType to be bound to Integer behavior, because my protocol methods will depend on this restriction" - in this case you can want to use typealias SomeType: IntegerType in your protocol, and then in your class continue to assign the type to this alias that matches IntegerType .

UPDATE

After uncovering a bug with Apple and a wide discussion around it, I realized that the main problem lies at the heart of this:

according to the protocol, you cannot directly refer to the associated type, which was declared only inside this protocol

(note that when extending the protocol, the corresponding type is available, as you would expect)

So, in the source code example:

 protocol SomeProtocol { typealias SomeType = Int func someFunc(someVar: SomeType) } class SomeClass: SomeProtocol { func someFunc(someVar: SomeType) { // use of undeclared type "SomeType" print(someVar) } } 

... re error: "use of undeclared type" is correct, your SomeClass class SomeClass not declare SomeType type

However, the extension to SomeProtocol has access to the associated type and can refer to it when providing an implementation:

(note that this requires using the where clause to determine the requirements for the corresponding type)

 protocol SomeProtocol { typealias SomeType = Int func someFunc(someVar: SomeType) } extension SomeProtocol where SomeType == Int { func someFunc(someVar: SomeType) { print("1 + \(someVar) = \(1 + someVar)") } } class SomeClass: SomeProtocol {} SomeClass().someFunc(3) // => "1 + 3 = 4" 
+5
source share

great article that actually gives you the answer to your question. I suggest everyone read it to go into type aliases and some more advanced things that appear when you use it.

Quote from the website:

It’s clear that there are no common protocols in Swift. But using typealias we can declare the required alias for another type.

+1
source share

All Articles