Может ли кто-нибудь объяснить в Swift, как переопределить свойство суперкласса другим объектом, унаследованным от исходного свойства?
Возьмем этот простой пример:
class Chassis {}
class RacingChassis : Chassis {}
class Car {
let chassis = Chassis()
}
class RaceCar: Car {
override let chassis = RacingChassis() //Error here
}
Это дает ошибку:
Cannot override with a stored property 'chassis'
Если вместо этого у меня есть шасси как var, я получаю сообщение об ошибке:
Cannot override mutable property 'chassis' of type 'Chassis' with covariant type 'RacingChassis'
Единственное, что я смог найти в руководстве в разделе «Переопределение свойств», указывает на то, что мы должны переопределить методы получения и установки, которые могут работать для изменения значения свойства (если это 'var'), но как насчет изменения класса свойства ?
strong
свойством, и я получал ошибку при попытке переопределить его, но, похоже, я пропустил, что он переводится как «неявно развернутый необязательный» (chassis!
) в Свифт, такoverride var chassis : Chassis!
исправляет.Кажется, это работает
источник
let
вCar
классе, что делает невозможным его изменение. Мы можем только изменитьchassis
свойствоRaceCar
класса.Попробуй это:
Затем:
Подробно на http://www.mylonly.com/14957025459875.html.
источник
Предоставленный Solution Dash работает хорошо, за исключением того, что суперкласс должен быть объявлен с ключевым словом let, а не var. Вот решение, которое возможно, но НЕ РЕКОМЕНДУЕТСЯ!
Приведенное ниже решение будет компилироваться с Xcode 6.2, SWIFT 1.1 (если все классы находятся в разных быстрых файлах), но его следует избегать, потому что ЭТО МОЖЕТ ПРИВЕСТИ К НЕОЖИДАННОМУ ПОВЕДЕНИЮ (ВКЛЮЧАЯ АВАРИЯ, особенно при использовании необязательных типов). ПРИМЕЧАНИЕ: ЭТО НЕ РАБОТАЕТ С XCODE 6.3 BETA 3, SWIFT 1.2.
источник
Теоретически можно так делать ...
Это отлично работает на игровой площадке Xcode.
Но если вы попробуете это в реальном проекте, ошибка компилятора сообщит вам:
На данный момент я проверял только Xcode 6.0 GM.
К сожалению, вам придется подождать, пока Apple исправит это.
Я тоже отправил отчет об ошибке. 18518795
источник
Я видел множество причин, по которым разработка API с использованием переменных вместо функций является проблематичной, и для меня использование вычисленных свойств кажется обходным решением. Есть веские причины держать переменные экземпляра инкапсулированными. Здесь я создал автомобильный протокол, которому соответствует автомобиль. У этого протокола есть метод доступа, который возвращает объект Chassis. Поскольку Car соответствует ему, подкласс RaceCar может переопределить его и вернуть другой подкласс Chassis. Это позволяет классу Car программировать интерфейс (автомобиль), а класс RaceCar, который знает о RacingChassis, может напрямую обращаться к переменной _racingChassis.
Еще один пример того, почему разработка API с использованием переменных не работает, - это когда у вас есть переменные в протоколе. Если вы хотите разбить все функции протокола на расширения, вы можете, за исключением того, что сохраненные свойства не могут быть помещены в расширения и должны быть определены в классе (чтобы это скомпилировалось, вам нужно раскомментировать код в AdaptableViewController и удалите переменную режима из расширения):
В приведенном выше коде будет ошибка компилятора: «Расширения могут не иметь сохраненных свойств». Вот как вы можете переписать приведенный выше пример, чтобы все в протоколе можно было отделить в расширении, используя вместо этого функции:
источник
Вы можете добиться этого с помощью дженериков:
При таком подходе у вас будет 100% безопасный код без принудительных развертываний.
Но это своего рода уловка, и если вам нужно будет переопределить несколько свойств, то объявления классов будут выглядеть как полный беспорядок. Так что будьте осторожны с этим подходом.
источник
В зависимости от того, как вы планируете использовать свойство, самый простой способ сделать это - использовать дополнительный тип для вашего подкласса и переопределить
didSet {}
метод для супер:Очевидно, вам нужно потратить некоторое время на проверку, чтобы убедиться, что классы могут быть инициализированы таким образом, но, установив для свойств значение optional, вы защитите себя от ситуаций, когда приведение больше не работает.
источник
Вы можете просто создать другую переменную RacingChassis.
источник
chassis
и позволив нам получить / установить нашRacingChassis
экземпляр соchassis
свойством.Попробуй это:
источник
источник
Следующее позволяет использовать один объект в базовом и производном классах. В производном классе используйте свойство производного объекта.
источник
Небольшое изменение других ответов, но проще и безопаснее с некоторыми приятными преимуществами.
Преимущества заключаются в том, что нет ограничений на то, какое шасси должно быть (var, let, optional и т. Д.), А также легко создать подкласс RaceCar. Подклассы RaceCar могут иметь собственное вычисленное значение для шасси (или racingChassis).
источник
просто установите новое свойство imageview с другим соглашением об именах, например imgview, потому что imageView уже является собственным свойством, и мы не можем назначить 2 сильных свойства.
источник