Swift: В чем разница между typealias и ассоциированным типом со значением в протоколе? - PullRequest
0 голосов
/ 11 апреля 2019

В Swift следующий код компилируется без проблем.

protocol P1 {
    associatedtype T = Int
}

protocol P2 {
    typealias T = Int
}

Мне кажется, они ведут себя почти одинаково. Единственное отличие, которое я заметил, состоит в том, что существуют дополнительные ограничения на использование P1, поскольку он имеет связанный тип. В частности, let x: P1 является ошибкой, в то время как let x: P2 в порядке.

Какова действительная разница между этими двумя протоколами? Они обрабатываются по-разному в скомпилированном коде? И наконец, есть ли преимущество в использовании P1 вместо P2?

Изменить для ясности:

Я знаю рабочую разницу между связанными типами и псевдонимами типов, поэтому я удивлен, что вам даже разрешено присвоить ассоциированному типу фиксированное значение. Это, кажется, побеждает всю цель связанного типа. Мне интересно, есть ли какая-либо утилита для присвоения ассоциированному типу фиксированного значения, и мне интересно, отличаются ли эти два протокола после компиляции.

1 Ответ

2 голосов
/ 11 апреля 2019

В написанном вами коде на самом деле нет функциональной разницы, потому что вы установили associatedType как Int.

Чтобы получить более мощное использование из них, вы можете использовать associatedType в качестве псевдо-общего ограничения.

Так что вы можете написать это так ...

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

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

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

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

Поскольку они оба соответствуют P1, и они оба устанавливают свой тип массива на Equatable типы. Компилятор может определить правильный тип функции add(item: Item) и помочь во время компиляции.

В отличие от этого ... typealias действительно используется только для изменения названия какого-либо типа для удобства. Например, вы можете использовать замыкание во многом как ... (Data?, Error?, URLResponse) -> (), и было бы долго писать его много раз, но при этом оно теряло бы часть смысла. Так что вы могли бы сделать ...

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

и замените все употребления на DownloadResponse.

В Swift есть множество отличных ресурсов по ассоциированному типу ...

  1. Взлом со Swift
  2. Наташа Робот
  3. Средний
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...