2017-01-05 3 views
4

У меня есть проблема с дженериков в Swift (3):Swift Дженерики с Protocol.Type

я получаю различные данные различных классов, реализуя тот же протокол, с сервера, и мне нужно, чтобы поместить их в класс с generics (например, Array).

Я не знаю, какой класс данных будет, поэтому мне нужно использовать протокол. Поэтому у меня есть следующая структура:

Мой протокол:

protocol MyProtocol { 
    // some protocol stuff 
} 

Некоторых классы, реализующего протокол

class MyProtocolImpl1: MyProtocol{ 
    // some class stuff 
} 

class MyProtocolImpl2: MyProtocol { 
    // some class stuff 
} 
.... 

класс с общим:

final class MyGenericsClass<T: MyProtocol> { 
    // some class stuff 
} 

теперь я хочу использовать этот класс таким образом:

func createClass<T>(model: T.Type) -> MyGenericClass<T> { 
    let myClass = MyGenericClass<T>() 
    return myClass 
} 

... 

EDIT

func getClass() -> MyProtocol.Type { 
    return MyProtocolImpl1.self 
} 

let impl1 = getClass() 
let impl2 = MyProtocolImpl2.self 

let createdClass = createClass(impl1) //not working 
let createdClass = createClass(impl2) //working 

делает createClass(impl1) я получаю эту ошибку:

cannot invoke 'createClass' with an argument list of type '(MyProtocol.Type)'

Изменение MyProtocol к классу будет решить эту проблему, но тогда я не мог быть уверен, что каждый класс наследование от него реализует необходимые методы.

Есть ли у кого-то идеи, как решить эту проблему?

+1

Выполняет ли 'func createClass ' исправление? – BallpointBen

+0

Вы могли решить проблему? –

+1

Ну, вы хотите передать 'MyProtocol.self' в функцию, а не' MyProtocol.Type'. Но даже тогда у вас не может быть «MyGenericClass », поскольку «MyProtocol» не является типом, который соответствует «MyProtocol» - см. [Протокол не соответствует самому себе?] (Http://stackoverflow.com/questions/ 33112559/protocol-doesnt-соответствовать-самому себе) – Hamish

ответ

0

Я точно не понял, что вы пытаетесь сделать, но я думаю, что это то, что вы хотите.

import Foundation 


protocol MyProtocol { 
} 

class ClassA : MyProtocol { 
} 

class ClassB : MyProtocol { 
} 

final class GenericClass<T:MyProtocol> { 

} 

func createClass<T:MyProtocol>(_ model: T.Type) -> GenericClass<T> { 
    let myClass = GenericClass<T>() 
    return myClass 
} 
let createdClass = createClass(ClassA.self) 
+0

Проблема в том, что я не знаю, является ли это ClassA или ClassB или ClassX. Я просто знаю, что это подкласс MyProtocol – beal

1

Ответ в том, что вы не можете сделать это. MyProtocol.self is не конкретный тип, ergo не может соответствовать MyProtocol. Вы не можете пройти MyProtocol, когда ваша функция ожидает конкретного типа T, следуя T: MyProtocol.

Подумайте об этом таким образом; если бы я добавил статическую функцию, doFoo() - MyProtocol, и вы инициализировали GenericClass<MyProtocol> и решили вызвать MyProtocol.doFoo() внутри какого-то метода, какую функцию он мог бы назвать? Это не имеет никакого смысла, потому что MyProtocol не является конкретным типом (т. Е. Классом, структурой или перечислением), - это протокол.


примечание на ваш комментарий:

The problem is that I do not know if it is ClassA or ClassB or ClassX. I just know that it is a subclass of MyProtocol

Здесь вы заблудших. «Подкласс MyProtocol» не имеет смысла, потому что MyProtocol is не класс.


Как насчет этого?В итоге вы получите AnyObject, но вы можете направить его на MyGenericClass<T> позже, когда вы do знаете T.

extension MyProtocol 
{ 
    static func createMyGenericClass() -> AnyObject 
    { 
     return MyGenericClass<Self>() 
    } 
} 

func createClass(_ modelType: MyProtocol.Type) -> AnyObject 
{ 
    return modelType.createMyGenericClass() 
} 

Вы также могли бы сделать MyGenericClass наследоваться от некоторого базового класса, а есть, которые хранят переменную для MyProtocol.Type. Таким образом, вы можете использовать определенные функции из вашего типа контентов MyProtocol.

+0

Спасибо за ответ. Но это не решает мою проблему. Я отредактировал вопрос, чтобы сделать его более ясным. Я хочу передать реализацию MyProtocol в 'createClass()' e. г. 'MyProtocolImpl.self' – beal

+0

Интересные решения, но они не работают для меня: В вашем первом решении я не могу использовать' Any', потому что он известен только во время выполнения. Ваше второе решение не будет работать в моем случае, потому что 'MyGenericClass' происходит из фреймворка – beal

+0

@ user7302727: Все классы Swift являются внутренними классами Objective-C. Вы можете использовать связанные объекты для хранения вашего типа 'MyProtocol' (например,' ClassA.self', 'ClassB.self') в экземпляре' MyGenericClass'. –

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