«X11 / Xlib.h»: нет такого файла или каталога на Mac OS X Mountain Lion

Ответ RobNapier (как обычно) неплохой, но только для альтернативной перспективы, которая может оказаться еще более просветляющей ...

О связанных типах

Протокол представляет собой абстрактный набор требований - контрольный список, который должен выполнить конкретный тип, чтобы сказать, что он соответствует протоколу. Традиционно считается, что этот контрольный список поведения: методы или свойства, реализованные конкретным типом. Связанные типы - это способ наименования вещей, которые участвуют в таком контрольном списке, и тем самым расширяя определение, сохраняя при этом его открытый конец как , как соответствующий тип реализует соответствие.

Когда вы видите:

protocol SimpleSetType {
    associatedtype Element
    func insert(_ element: Element)
    func contains(_ element: Element) -> Bool
    // ...
}

Что означает, что для типа, требующего соответствия SimpleSetType, не только этот тип содержит функции insert(_:) и contains(_:), эти две функции должны принимать тот же тип параметра, что и друг друга. Но не имеет значения, каков тип этого параметра.

Вы можете реализовать этот протокол с помощью общего или нестандартного типа:

class BagOfBytes: SimpleSetType {
    func insert(_ byte: UInt8) { /*...*/ }
    func contains(_ byte: UInt8) -> Bool { /*...*/ }
}

struct SetOfEquatables<T: Equatable>: SimpleSetType {
    func insert(_ item: T) { /*...*/ }
    func contains(_ item: T) -> Bool { /*...*/ }
}    

Обратите внимание, что нигде BagOfBytes или SetOfEquatables определяют соединение между SimpleSetType.Element и типом, используемым в качестве параметра для их двух методов - компилятор автоматически выполняет то, что эти типы связаны с правильными методами, поэтому они отвечают требованиям протокола для связанного типа .

В параметрах общего типа

Если связанные типы расширяют ваш словарь для создания абстрактных контрольных списков, параметры типового типа ограничивают реализацию конкретного типа. Когда у вас есть общий класс:

class ViewController<V: View> {
    var view: V
}

Он не говорит, что существует множество разных способов сделать ViewController (пока у вас есть view), это говорит, что ViewController - настоящая конкретная вещь , и она имеет view. Кроме того, мы точно не знаем, какой вид имеет данный экземпляр ViewController, но мы знаем, что он должен быть View (либо подклассом класса View, либо типом, реализующим View ... мы не говорим).

Или, говоря иначе, писать общий тип или функцию - это своего рода ярлык для написания реального кода. Возьмем этот пример:

func allEqual<T: Equatable>(a: T, b: T, c: T) {
    return a == b && b == c
}

Это имеет такой же эффект, как если бы вы проходили все типы Equatable и писали:

func allEqual(a: Int, b: Int, c: Int) { return a == b && b == c }
func allEqual(a: String, b: String, c: String) { return a == b && b == c }
func allEqual(a: Samophlange, b: Samophlange, c: Samophlange) { return a == b && b == c }

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

TLDR

] Ассоциированные типы и параметры типового типа - это очень разные виды инструментов: связанные типы - это язык описания, а generics - язык реализации. У них очень разные цели, хотя их использование иногда выглядит одинаково (особенно когда речь идет о тонких взглядах на такие взгляды между абстрактным планом для коллекций любого типа элемента и фактическим типом коллекции, который все еще может иметь общий элемент). Поскольку они очень разные звери, у них есть другой синтаксис.

14
задан jasonkim 14 January 2013 в 15:08
поделиться