Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift: What is the difference between a typealias and an associatedtype with a value in a protocol?

In Swift, the following code compiles without issue.

protocol P1 {
    associatedtype T = Int
}

protocol P2 {
    typealias T = Int
}

To me, these appear to behave almost identically. The only difference I have noticed is that there are additional restrictions on when you can use P1 because it has an associated type. In particular, let x: P1 is an error while let x: P2 is fine.

What is the actual difference between these two protocols? Are they treated differently in compiled code? Lastly, is there ever an advantage to using P1 rather than P2?

Edit for clarity:

I know the working difference between associated types and type aliases, so I am surprised that you are even allowed to give an associated type a fixed value. That seems to defeat the entire purpose of an associated type. I am wondering if there is any utility to giving an associated type a fixed value, and I am wondering if these two protocols are different once compiled.

like image 595
deaton.dg Avatar asked Apr 10 '19 22:04

deaton.dg


People also ask

What does Typealias do in Swift?

In Swift, typealias is a function that gives a new name, or an alias, to an existing type. This type can be a concrete type, like Double or a custom structure, a compound type, like tuples, or a complex closure type.

What is Associatedtype in Swift?

An associated type gives a placeholder name to a type that's used as part of the protocol. The actual type to use for that associated type isn't specified until the protocol is adopted. Associated types are specified with the associatedtype keyword.

What is the use of Typealias?

A type alias allows you to provide a new name for an existing data type into your program. After a type alias is declared, the aliased name can be used instead of the existing type throughout the program. Type alias do not create new types. They simply provide a new name to an existing type.

What is self requirement?

A Self requirement is a placeholder in a protocol for a type, used as part of the protocol, which is replaced by the concrete type that conforms to the protocol. A Self requirement can thus be thought of as a special case of an associated type.


1 Answers

In the code you have written there isn't really a functional difference because you have set the associatedtype as Int.

To get more powerful usage out of them you can use the associatedtype as a pseudo generic constraint.

So you might write it like this...

protocol P1 {
    associatedtype Item: Equatable
    var itemArray: [Item] { get set }
    mutating func add(item: Item)
}

extension P1 {
    mutating func add(item: Item) {
        itemArray.append(item)
    }
}

struct StructWithStrings: P1 {
    var itemArray: [String]
}

struct StructWithInts: P1 {
    var itemArray: [Int]
}

Because they both conform to P1 and they both set their array type to Equatable types. The compiler can infer the correct type of the add(item: Item) function and help at compile time.

In contrast to this... typealias is only really used to change the name of some type for convenience. For instance you might use a closure a lot like... (Data?, Error?, URLResponse) -> () and it would be long to write it many times but also loses some of the meaning. So you could do...

typealias DownloadResponse = (Data?, Error?, URLResponse) -> ()

and replace all the usages with DownloadResponse.

There are loads of excellent resources about associatedtype in Swift...

  1. Hacking With Swift
  2. Natasha the Robot
  3. Medium
like image 190
Fogmeister Avatar answered Sep 22 '22 06:09

Fogmeister