2016-02-26 6 views
2

Как Swift Language Guide баллов из общих типов может быть сдерживающим фактором для классов или протоколов, как это:Как создать общий класс, который связан с структурами?

public class MyGenericClass<T:Equatable> { 
    func printEquality(a:T, b:T) { 
     if a == b { 
      print("equal") 
     } else { 
      print("not equal") 
     } 
    } 
} 

Могу ли я каким-то образом ограничить T быть struct?

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

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

protocol SomeClassOnlyProtocol: class, SomeInheritedProtocol { 
    // class-only protocol definition goes here 
} 
+0

Наследование относится только к классам (ссылочные типы). SomeInheritedProtocol не имеет смысла в Swift. Связано с протоколами - это соответствие. Однако проверка выполнения, если экземпляр какого-либо типа соответствует протоколу AnyObject или нет, доступен с помощью оператора – user3441734

+0

Близко связанный: http://stackoverflow.com/questions/33623104/how-to-restrict-a-protocol-to-value-types -одно: –

+0

@ user3441734 фрагмент кода - это цитата из главы «Протоколы» в Руководстве по языку Swift. – Klaas

ответ

2

Вы не можете (начиная с Swift 2.2).

Это просто невозможно. Существует struct версия AnyObject, то есть протокол AnyValue (автоматически реализуется для всех типов значений).

Я сам столкнулся с этой проблемой, и я сожалею, что нет другого решения, кроме как строго соблюдать неофициальный протокол. Вот в надежде, что Swift 3 решит это.

1

Другой ответ отвечает на это хорошо (то есть: вы не можете (еще?)).

Я думал, что добавлю, что вы можете, однако, имитировать хотя бы поведение этого, используя интроспекцию времени выполнения и неудачные инициализаторы; так что инициализация вашего универсального класса будет успешной только в том случае, если T является структурой (соответствующей Equatable).

public class MyGenericClass<T: Equatable> { 
    var foo: T 

    init?(bar: T) { 
     foo = bar 

     if Mirror(reflecting: foo).displayStyle != .Struct { 
      return nil 
     } 
    } 
} 

struct Foo : Equatable { 
    let foo = 1 
} 
func ==(lhs: Foo, rhs: Foo) -> Bool { return lhs.foo == rhs.foo } 

/* Example */ 
if let _ = MyGenericClass<Int>(bar: 1) { 
    print("Integer") 
} 
if let _ = MyGenericClass<Foo>(bar: Foo()) { 
    print("Foo-Struct") 
} 
// prints only "Foo-Struct" 

Вы могли бы интерпретировать не удались инициализацию, как несоответствие вашего общего T к «только позволяет T быть структурами», и, возможно, использовать опциональное связывание (/ ...), чтобы использовать это с классом наблюдателя на практике.

+0

в Swift an int struct, Double - фактически структура и т. Д. Вы можете проверить соответствие AnyObject (и несоответствию) с If bar - AnyObject {// bar - ссылочный тип, class} else {// bar - тип значения, struct } не смешивайте тип и displayStyle !!! – user3441734

+0

@ user3441734 Я интерпретировал вопрос OP: s относительно ограничения протокола «быть структурой» в смысле явных типов структуры (а не нативных типов, которые по своей сути находятся за капюшоном, структурами). Отражение на родных типах значений будет возвращать 'nil' для' .displayStyle', следовательно, разрешая только «чистые структуры» в приведенном выше примере. Если бы ОП попросил _ «сдерживать общий тип только для типов значений» _ (но не упоминать о структурах, в частности), то решение «AnyObject» - это хороший способ. Однако, поскольку я интерпретирую этот вопрос, это требует охвата всех типов значений (включая родные). – dfri

+0

@dfri спасибо за ваше решение. Я тоже думал о чем-то подобном. – Klaas

Смежные вопросы