2016-12-29 2 views
0

Я пытаюсь создать пару объектов, которые зависят друг от друга, и у них есть метод, чтобы сбрасывать непосредственно конкретный класс другого объекта. Что-то вроде этого:swift 3 downcast to dynamic class

protocol aProt 
{ 
    var bVar:bProt! { get set } 
} 

protocol bProt 
{ 
    var aVar:aProt! { get set } 
} 

class a: aProt 
{ 
    var bVar: bProt! 
    func bConcrete() -> b { 
     return bVar as! b 
    } 
} 

class b: bProt 
{ 
    var aVar: aProt! 
    func aConcrete() -> a { 
     return aVar as! a 
} 

Теперь проблема в том, что я хочу, чтобы это поведение (func aConcrete(),func bConcrete()) наследуются подклассами а и Ь. Затем я подумал, что идеальный способ сделать это - использовать дженерики, но ... Нет никакого способа сделать это.

класс a: aProt { var bVar: bProt! func bConcrete() -> T { возвращение bVar как! T } }

class b: bProt 
{ 
    var aVar: aProt! 
    func aConcrete<T>() -> T { 
     return aVar as! T 
} 

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

let aObject = a() 
let bSubclassObject = a.bConcrete() // The compiler complains it cannot infer the class of T 
let bSubclassObject = a.bConcrete() as! bSubclass // this works, but this is exactly which I wanted to avoid... :(
+0

Если вы спускаетесь так, как будто, то что-то сломано. Вам никогда не придется сворачивать с протокола на конкретную реализацию. Для этого нужны протоколы. – Fogmeister

+0

Что должен делать компилятор? Вы говорите «отбрасываете этот объект bVar», а затем продолжаете «... вводить T, но я не собираюсь говорить вам, что такое T». – luk2302

+0

@Fogmeister Я пытаюсь создать общую ссылку от одной к другой (a и b), но в конкретной реализации они всегда будут подклассифицированы, поэтому мне нужно опустить результат –

ответ

1

Определите общую функцию и добавить, где T:

protocol aProt { 
    var bVar: bProt! { get set } 
} 

protocol bProt { 
    var aVar:aProt! { get set } 
} 

class a: aProt { 
    var bVar: bProt! 
    func bConcrete<T: b>(_ type: T.Type) -> T? { 
     return bVar as? T 
    } 
} 

class b: bProt { 
    var aVar: aProt! 
    func aConcrete<T: a>(_ type: T.Type) -> T? { 
     return aVar as? T 
    } 
} 

class a1: a { } 
class b1: b { 
    var fullName: String = "new object" 
} 

let aObj = a() 
aObj.bVar = b1() 
let bObj = aObj.bConcrete(b1.self) 
bObj?.fullName 

по вашему требованию, вызывает bConcrete (b1.self) может еще не достаточно хорошо, но, по крайней мере, вам нужно чтобы узнать, какой тип данных вы ожидаете вернуть.

+0

Это почти то, чего я хотел достичь, но когда я пытаюсь получить доступ к новому методу/свойству, определенному на b1, компилятор жалуется :( –

+0

Когда вы вызываете bConcrete(), знаете ли вы, какой тип возврата будет? Если функция изменено на 'func bConcrete (_ type: T.Type) -> T?' было бы полезно? – bubuxu

+0

Дело в том, что я хотел не сообщать компилятору тип. Если я говорю типу, тогда нет смысла создавать функция, потому что downcasting с использованием «as» является более простым ... (например, проще написать 'aObjc.bVar как b1') –