Swift 2 Generic структура данных не соответствует протоколу Equatable

Я работаю над созданием гибкой структуры данных в Swift под названием Node, которая сама по себе не привязана к какому-либо типу контента. Однако данные полезной нагрузки в узле объявляются как следующая общая структура элемента, которая соответствует протоколу Equatable:

public struct Element<T>: Equatable {
  var data: T;
}

public func ==<T:Equatable>(lhs: Element<T>, rhs: Element<T>) -> Bool {
    return lhs.data == rhs.data;
}

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

public class Node: Equatable {

    var payload: Element<AnyObject>

    init(_data: Element<AnyObject>) {
        self.payload = _data
    }

}

public func ==(lhs: Node, rhs: Node) -> Bool {
    return lhs.payload == rhs.payload;
}

Конечно, я получаю сообщение об ошибке, что AnyObject не соответствует Equatable. Есть ли способ ограничить объявление полезной нагрузки только объектами, которые эквивалентны? На данный момент я не знаю, какие объекты могут храниться в полезной нагрузке.

Также только что понял, что мне нужно поставить проверку класса в функции == в Node, чтобы убедиться, что две полезные нагрузки Node совместимы для сравнения - не нужно, чтобы они были.

Мысли? Спасибо!


person Alex Ackerman    schedule 25.02.2016    source источник
comment
Ваша вторая реализация == относится к lhs.data и rhs.data, где lhs и rhs - это узлы. Но ваш класс Node не имеет свойства data, поэтому я не понимаю, что это должно означать. Вы имели в виду lhs.payload и rhs.payload?   -  person matt    schedule 25.02.2016
comment
да. Я сделал некоторые упрощения и забыл это изменить. Он должен читать lhs.payload и rhs.payload.   -  person Alex Ackerman    schedule 25.02.2016


Ответы (1)


Чтобы ограничить payload типом Equatable, вам нужно, чтобы Node был универсальным классом, чтобы он мог передавать это ограничение.

Вы можете указать ограничение в объявлении вашего класса:

public class Node<T: Equatable>: Equatable {...}

А затем, объявляя полезную нагрузку, вы можете установить для нее тип элемента только T:

var payload: Element<T>

При тестировании кода мне также пришлось сделать так, чтобы общее ограничение T в Element соответствовало Equatable. Весь код для справки:

public struct Element<T: Equatable>: Equatable {
    var data: T
}

public func ==<T:Equatable>(lhs: Element<T>, rhs: Element<T>) -> Bool {
    return lhs.data == rhs.data
}

public class Node<T: Equatable>: Equatable {
    var payload: Element<T>
    init(_data: Element<T>) {
        self.payload = _data
    }
}

public func ==<T: Equatable>(lhs: Node<T>, rhs: Node<T>) -> Bool {
    return lhs.payload == rhs.payload
}

Это даст следующие результаты:

Node(_data: Element(data: 1)) == Node(_data: Element(data: 1)) // true
Node(_data: Element(data: 1)) == Node(_data: Element(data: 2)) // false
person Tony Albor    schedule 13.09.2016
comment
Потрясающие! Спасибо! - person Alex Ackerman; 13.09.2016