2015-01-14 4 views
16

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

ответ

29
управления

доступа по линиям наследования не очень подходит к конструированию философий за Swift и какао:

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

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

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

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

Дополнительное разъяснение on Apple's Swift blog.

+0

http://owensd.io/2014/08/21/protected-swift.html – nwales

+0

Это интересное предложение, и в нем могут быть достоинства. (Лично я не уверен, это помогло бы увидеть более конкретный вариант использования.) Несмотря на это, похоже, повторное использование имени 'protected' для другой цели, чем тот, о котором вы спрашиваете (а также разные от того, что означает это имя на других языках). – rickster

+22

Я думаю, что защищенный, поскольку он существует на других языках программирования, должен существовать в Swift. В принципе, если вы хотите поделиться частным определением с вашими потомками, вы не сможете. Это раздражает. –

1

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

Вы определяете как базовый класс, так и подкласс в одном файле .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 имеет какие-либо планы по его поддержке).

1

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

class Parent { 
    fileprivate var someProperty: Any? 
} 

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

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

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