Как сделать свойство экземпляра видимым только для подкласса swift

Я пытаюсь объявить свойство экземпляра в swift так, чтобы он был виден только классу и подклассам. Я считаю, что это будет называться охраняемым имуществом на других языках. Есть ли способ достичь этого в Swift?

Ответы

Ответ 1

Контроль доступа по линиям наследования не соответствует идеям дизайна Swift и Cocoa:

При разработке уровней контроля доступа в Swift мы рассмотрели два основных варианта использования:

  • сохранить private информацию о классе, скрытом от остальной части приложения
  • сохранить internal информацию о структуре, скрытой от клиентского приложения

Соответствуют уровням доступа private и internal соответственно.

В отличие от этого, protected объединяет доступ с наследованием, добавляя совершенно новую ось управления. Он фактически не предлагает никакой реальной защиты, поскольку подкласс всегда может выставлять "защищенный" API через новый публичный метод или свойство. Он также не предлагает дополнительных возможностей оптимизации, поскольку новые переопределения могут поступать из любого места. И его излишне ограничительный - он позволяет подклассам, но не любым помощникам подклассов, получить доступ к чему-либо.

Далее объясняется в блоге Apple Swift.

Ответ 2

Я нашел способ (не правильный путь в соответствии с другими стандартными объектно-ориентированными языками программирования).

Вы определяете как базовый класс, так и подкласс в одном файле .swift. Затем вы можете получить доступ к закрытым полям вашего базового класса.

Ниже классов буксировки определены в файле BaseClass.swift

class BaseClass {
    private var privateVariable : Int

    init ()
    {
        privateVariable = 0
    }

    private func doSomeThing () -> Void
    {
        privateVariable += 10
    }
}

class SubClass: BaseClass {

    override init() {

        super.init()

        privateVariable = 1
    }

    private override func doSomeThing() {
        super.doSomeThing()
        privateVariable *= 10
    }
}

Это даст вашему подклассу возможность доступа к приватным переменным.

Убедитесь, что вы определяете как базовый класс, так и подкласс в том же быстром файле.

Но проблема здесь еще не решена. Проблемы с безопасностью. Вы не всегда можете позволить подклассу обращаться к закрытым полям вашего родительского класса. Для этого вы можете определить расширение вашего подкласса, где частные члены родительского класса недоступны. Просто попробуйте один раз.

extension SubClass
{
    func doSomeOtherThing() -> Void {
        privateVariable = 0; // This is a compiler error.
    }
}

Это расширение определено в файле SubClass.swift.

Если вы согласны с этим, используйте это, иначе дождитесь, пока Apple согласится использовать защищенный модификатор в предстоящей версии Swift (не уверен, что 3.1 или 3.x или v4.0 имеет какие-либо планы поддержки).

Ответ 3

Один из способов сделать это - определить функцию или свойство с ключевым словом fileprivate и определить подкласс в том же файле, что и так:

class Parent {
    fileprivate var someProperty: Any?
}

class Child: Parent {
    func someFunction() {
        print(someProperty)
    }
}

Конечно, это очень раздражает, так как этот файл будет огромным беспорядком. Не говоря уже о том, почему Swift позволяет это, но не protected просто... argh.