2016-05-04 2 views
1

Вот пример хорошего старого класса мода одиночного наследование OO дерева:Swift типов и хорошее старомодное иерархическое одиночное наследование

class Common { 
    var foo:String = "" 
    var bar:Int = 0 
    // common behavior to deal with foo + bar 
} 

class SubA:Common { 
    var yak:Double = 0.0 
    // specialized behavior to deal with yak, foo, and bar 
} 

class SubB:Common { 
    var baz:CGFloat = 1.0 
    // specialized behavior to deal with baz, foo, and bar 
} 

Довольно просто. Свифт дает нам много новых способов думать о вещах, но это все еще очень распространенная парадигма ОО и часто стоит использовать. Если я хочу создать ViewControllers, которые взаимодействуют с ними, заманчиво следовать той же схеме:

class CommonViewController:UIViewController { 
    var model:Common! 
    // common behavior to deal with the common behavior found in the Common superclass 
} 

class SubAViewController:CommonViewController { 
    var model:SubA! 
    // more methods to deal with the specializations that SubA provides 
} 

class SubBViewController:CommonViewController { 
    var model:SubB! 
    // more methods to deal with the specializations that SubA provides 
} 

Опять же, довольно стандартная конструкция. К сожалению, система типа Swift не позволяет:

error: cannot override mutable property 'model' of type 'Common!' with covariant type 'SubA!' 
    var model:SubA! 

Есть ли легко решить эту проблему? Простейшие я мог думать о том, чтобы сделать суб ViewControllers как:

class SubAViewController:CommonViewController { 
    var subA:SubA { 
     get { 
      return self.model as! SubA 
     } 
     set { 
      self.model = newValue 
     } 
    } 
    // some behavior will need to use self.subA to get that type of data 
} 

class SubBViewController:CommonViewController { 
    var subB:SubB { 
     get { 
      return self.model as! SubB 
     } 
     set { 
      self.model = newValue 
     } 
    } 
    // some behavior will need to use self.subA to get that type of data 
} 

Это добавляет 2 имели к делать-это-к-косметической его-метода работы и ограничение, что некоторые из моих методов подкласса необходимо обратиться к self.subB или self.subA, а не к self.model. Я начал работать над тем, как это сделать с протоколами и расширениями, но я просто чувствовал, что добавляю все больше и больше обручей, чтобы сделать решение таким, каким я хотел. Есть ли более простое решение, которое можно использовать с Swift для реализации этого очень классического и общего шаблона наследования OO?

ответ

1

Короче говоря, вы не можете этого сделать. Вы должны добавить новое свойство с другим типом и предоставить getter и setter тот, который переопределен. Аналогичный случай можно найти здесь: Overriding superclass property with different type in Swift

1

То, что вы пытаетесь сделать, это не разрешается в любой сильно и статически типизированный объектно-ориентированный язык, а не только в Swift.

Рассмотрим, например, функцию f, которая приобретает объект типа CommonViewController. Эта функция может, например, изменить переменную объекта model с новым значением, экземпляром класса Common.

Тогда вы можете перейти к f значение типа SubAViewController, что было бы законным, так как его тип был бы подтипом CommonViewController. Когда f присваивает своему атрибуту model новое значение типа Common, это нарушает объявление типа model внутри SubAViewController, и это может вызвать ошибку типа времени выполнения, которая не допускается на таких языках.

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