У Swift есть модификаторы доступа?
Данные объекта Objective-C могут быть public
, protected
или private
. Например:
@interface Foo : NSObject { @public int x; @protected: int y; @private: int z; } -(int) apple; -(int) pear; -(int) banana; @end
Я не нашел упоминания о модификаторах доступа в ссылке Swift. Возможно ли ограничить видимость данных в Swift?
С Swift 3.0.1 существует 4 уровня доступа , описанных ниже с наивысшего (наименее ограничительного) до самого низкого (наиболее ограничительного).
1. open
и public
Включить сущность, которая будет использоваться вне определяющего модуля (цели). Обычно вы используете open
или public
доступ при указании открытого интерфейса на фреймворк.
Однако open
доступ применяется только к classам и членам classа , и он отличается от public
доступа следующим образом:
-
public
classы и члены classа могут быть только подclassифицированы и переопределены в определяющем модуле (цели). -
open
classы и члены classа могут быть подclassифицированы и переопределены как внутри, так и вне определяющего модуля (цели).
// First.framework – A.swift open class A {}
// First.framework – B.swift public class B: A {} // ok
// Second.framework – C.swift import First internal class C: A {} // ok
// Second.framework – D.swift import First internal class D: B {} // error: B cannot be subclassed
2. internal
Позволяет использовать объект в определяющем модуле (цели). Обычно вы используете internal
доступ при определении внутренней структуры приложения или внутренней структуры.
// First.framework – A.swift internal struct A {}
// First.framework – B.swift A() // ok
// Second.framework – C.swift import First A() // error: A is unavailable
3. fileprivate
Ограничивает использование сущности в определяющем исходном файле. Обычно вы используете доступ к файлам, чтобы скрыть детали реализации определенной функциональности, когда эти данные используются во всем файле.
// First.framework – A.swift internal struct A { fileprivate static let x: Int } Ax // ok
// First.framework – B.swift Ax // error: x is not available
4. private
Ограничивает использование объекта в его объявлении. Обычно вы используете private
доступ, чтобы скрыть детали реализации определенной функциональности, когда эти данные используются только в рамках одной декларации.
// First.framework – A.swift internal struct A { private static let x: Int internal static func doSomethingWithX() { x // ok } } Ax // error: x is unavailable
Когда вы говорите о создании «частного метода» в Swift или ObjC (или ruby или java или …), эти методы не являются действительно частными. Их нет. Любой язык, который предлагает даже небольшую интроспекцию, позволяет разработчикам получать эти ценности извне classа, если они действительно этого хотят.
Так что мы действительно говорим здесь, это способ определить открытый интерфейс, который просто представляет функциональность, в которой мы хотим, и «скрывает» остальное, что мы считаем «частным».
Механизм Swift для объявления интерфейсов является protocol
, и его можно использовать для этой цели.
protocol MyClass { var publicProperty:Int {get set} func publicMethod(foo:String)->String } class MyClassImplementation : MyClass { var publicProperty:Int = 5 var privateProperty:Int = 8 func publicMethod(foo:String)->String{ return privateMethod(foo) } func privateMethod(foo:String)->String{ return "Hello \(foo)" } }
Помните, что протоколы являются первоclassными типами и могут использоваться везде, где может быть тип. И , когда они используются таким образом, они раскрывают только свои интерфейсы, а не те, которые применяются для типа реализации.
Таким образом, до тех пор, пока вы используете MyClass
вместо MyClassImplementation
в своих типах параметров и т. Д., Все должно работать:
func breakingAndEntering(foo:MyClass)->String{ return foo.privateMethod() //ERROR: 'MyClass' does not have a member named 'privateMethod' }
Есть некоторые случаи прямого назначения, где вы должны быть явным с типом, вместо того, чтобы полагаться на Свифт, чтобы сделать вывод, но это вряд ли кажется нарушителем сделки:
var myClass:MyClass = MyClassImplementation()
Использование протоколов таким образом семантично, достаточно кратким, и мои глаза очень похожи на classы, которые мы использовали для этой цели в ObjC.
Насколько я могу судить, нет ключевых слов «public», «private» или «protected». Это предполагает, что все будет общедоступным.
Однако Apple может ожидать, что люди будут использовать « протоколы » (называемые интерфейсами остальным миром) и шаблон фабричного проектирования, чтобы скрыть детали типа реализации.
Это часто хороший шаблон дизайна для использования в любом случае; поскольку он позволяет вам изменить иерархию classов реализации , сохраняя при этом систему логического типа одинаковой.
Используя комбинацию протоколов, закрытий и вложенных / внутренних classов, можно использовать что-то по строкам шаблона модуля, чтобы скрыть информацию в Swift прямо сейчас. Это не супер чистое или приятное чтение, но оно действительно работает.
Пример:
protocol HuhThing { var huh: Int { get set } } func HuhMaker() -> HuhThing { class InnerHuh: HuhThing { var innerVal: Int = 0 var huh: Int { get { return mysteriousMath(innerVal) } set { innerVal = newValue / 2 } } func mysteriousMath(number: Int) -> Int { return number * 3 + 2 } } return InnerHuh() } HuhMaker() var h = HuhMaker() h.huh // 2 h.huh = 32 h.huh // 50 h.huh = 39 h.huh // 59
innerVal и mysteriousMath скрыты здесь извне, а попытка проникнуть в объект должна привести к ошибке.
Я только часть своего чтения документов Swift, поэтому, если есть недостаток, пожалуйста, укажите это, хотелось бы узнать.
Swift 4
Как указано в Swift Documentation – Access Control , Swift 4 имеет 5 элементов управления доступом :
-
открытые и общедоступные : могут быть доступны из объектов своего модуля и любых объектов модуля, которые импортируют определяющий модуль.
-
internal : доступ к ним возможен только от объектов своего модуля. Это уровень доступа по умолчанию.
-
fileprivate и private : доступ к ним возможен только в ограниченном объеме, где вы их определяете.
В чем разница между открытым и общественным ?
open – это то же самое, что и public в предыдущих версиях Swift, они позволяют использовать classы из других модhive и наследовать их, т. е. они могут быть подclassифицированы из других модhive. Кроме того, они позволяют членам других модhive использовать и переопределять их. Та же логика распространяется на их модули.
public разрешают classы из другого модуля использовать их, но не наследуют их, т. е. они не могут быть подclassифицированы из других модhive. Кроме того, они позволяют членам из других модhive использовать их, но НЕ переопределять их. Для своих модhive у них есть одна и та же открытая логика (они позволяют classам использовать и наследовать их, они позволяют членам использовать и переопределять их).
В чем разница между fileprivate и private ?
fileprivate можно получить из всех файлов.
частные могут быть доступны только из их единственного объявления и для расширений этого объявления, которые находятся в одном файле; Например:
// Declaring "A" class that has the two types of "private" and "fileprivate": class A { private var aPrivate: String? fileprivate var aFileprivate: String? func accessMySelf() { // this works fine self.aPrivate = "" self.aFileprivate = "" } } // Declaring "B" for checking the abiltiy of accessing "A" class: class B { func accessA() { // create an instance of "A" class let aObject = A() // Error! this is NOT accessable... aObject.aPrivate = "I CANNOT set a value for it!" // this works fine aObject.aFileprivate = "I CAN set a value for it!" } }
В чем разница между Swift 3 и Swift 4 Access Control?
Как упоминалось в предложении SE-0169 , в Swift 4 добавлено единственное уточнение, что область доступа к частному доступу была расширена, чтобы быть доступной из расширений этой декларации в том же файле; Например:
struct MyStruct { private let myMessage = "Hello World" } extension MyStruct { func printMyMessage() { print(myMessage) // In Swift 3, you will get a compile time error: // error: 'myMessage' is inaccessible due to 'private' protection level // In Swift 4 it should works fine! } }
Таким образом, нет необходимости объявлять myMessage
как fileprivate для доступа во всем файле.
Замечание боковой панели: если вы столкнулись с проблемами, связанными с некомпилированием Swift 4 с перенесенным старым проектом Swift 3, вы можете проверить это Q & A.
Начиная с Xcode 6 beta 4, у Swift есть модификаторы доступа. Из примечаний к выпуску:
Управление быстрым доступом имеет три уровня доступа:
- частные объекты могут быть доступны только из исходного файла, где они определены.
- внутренние объекты могут быть доступны в любом месте объекта, где они определены.
- публичные объекты могут быть доступны из любого места в пределах целевого объекта и из любого другого контекста, который импортирует модуль текущей цели.
Неявное значение по умолчанию является internal
, поэтому в пределах целевого приложения вы можете оставить модификаторы доступа, кроме случаев, когда вы хотите быть более ограничительными. В целевой среде (например, если вы внедряете фреймворк для совместного использования кода между приложением и расширением для общего доступа или сегодня), используйте public
для обозначения API, который вы хотите предоставить клиентам вашей инфраструктуры.
Swift 3.0 предоставляет пять различных элементов управления доступом:
- открытый
- общественности
- внутренний
- fileprivate
- частный
Объекты открытого доступа и доступа к общедоступному доступу должны использоваться в любом исходном файле из их определяющего модуля, а также в исходном файле из другого модуля, который импортирует определяющий модуль. Обычно вы используете открытый или общеansible доступ при указании открытого интерфейса на фреймворк.
Внутренний доступ позволяет сущности использоваться в любом исходном файле из своего определяющего модуля, но не в каком-либо исходном файле вне этого модуля. Обычно вы используете внутренний доступ при определении внутренней структуры приложения или внутренней структуры.
Файло-частный доступ ограничивает использование объекта в собственном определяющем исходном файле. Используйте файл-частный доступ, чтобы скрыть детали реализации определенной функциональности, когда эти данные используются во всем файле.
Частный доступ ограничивает использование объекта в объявлении. Используйте частный доступ, чтобы скрыть детали реализации определенной функциональности, когда эти данные используются только в рамках одной декларации.
Открытый доступ – это наивысший (наименее ограничительный) уровень доступа, а частный доступ – самый низкий (самый ограничительный) уровень доступа.
Уровни доступа по умолчанию
Все объекты в вашем коде (с несколькими конкретными исключениями) имеют уровень доступа по умолчанию для внутреннего пользователя, если вы не указали явный уровень доступа самостоятельно. В результате во многих случаях вам не нужно указывать явный уровень доступа в вашем коде.
Выпускная заметка по теме:
Классы, объявленные как public, больше не могут быть подclassифицированы вне их определяющего модуля, а методы, объявленные как public, больше не могут быть переопределены вне их определяющего модуля. Чтобы разрешить внешнему подclassу classа или переопределить внешний метод, объявите их открытыми, что является новым уровнем доступа, недоступным для публики. Импортированные classы и методы Objective-C теперь импортируются как открытые, а не общедоступные. Модульные тесты, которые импортируют модуль с использованием импорта @testable, все равно будут разрешены подclassифицировать общедоступные или внутренние classы, а также переопределять общедоступные или внутренние методы. (SE-0117)
Дополнительная информация и подробная информация: Быстрый язык программирования (контроль доступа)
Нет, это невозможно. Никаких частных / защищенных методов и переменных вообще нет.
Все открыто.
В бета-версии 6 в документации указано, что существует три разных модификатора доступа:
- общественного
- внутренний
- Частный
И эти три относятся к classам, протоколам, функциям и свойствам.
public var somePublicVariable = 0 internal let someInternalConstant = 0 private func somePrivateFunction() {}
Дополнительные сведения см. В разделе Контроль доступа .
Механизмы контроля доступа, представленные в Xcode 6 :
Swift предоставляет три разных уровня доступа для объектов внутри вашего кода. Эти уровни доступа относятся к исходному файлу, в котором определяется сущность, а также относительно модуля, к которому принадлежит исходный файл.
- Открытый доступ позволяет сущности использоваться в любом исходном файле из их определяющего модуля, а также в исходном файле из другого модуля, который импортирует определяющий модуль. Обычно вы используете общеansible доступ, указав публичный интерфейс на фреймворк.
- Внутренний доступ позволяет сущности использоваться в любом исходном файле из своего определяющего модуля, но не в каком-либо исходном файле вне этого модуля. Обычно вы используете внутренний доступ при определении внутренней структуры приложения или внутренней структуры.
- Частный доступ ограничивает использование объекта в его собственном определяющем исходном файле. Используйте частный доступ, чтобы скрыть детали реализации определенной функциональности.
Открытый доступ является наивысшим (наименее ограничительным) уровнем доступа, а частный доступ является самым низким (или самым ограничительным) уровнем доступа.
По умолчанию accecss он является внутренним , и как таковой не нужно указывать. Также обратите внимание, что частный спецификатор не работает на уровне classа, а на уровне исходного файла. Это означает, что для того, чтобы отдельные части classа были действительно частными, вам нужно разделить их на собственный файл. Это также приводит к некоторым интересным случаям в отношении модульного тестирования …
Еще один момент для меня, о котором говорится в ссылке выше, заключается в том, что вы не можете «обновить» уровень доступа. Если вы подclassируете что-то, вы можете ограничить его больше, но не наоборот.
Этот последний бит также влияет на функции, кортежи и, конечно же, на другие вещи таким образом, что если функция использует частный class, то недопустимо иметь внутреннюю или общедоступную функцию, поскольку у них может не быть доступа к частному classу. Это приводит к предупреждению компилятора, и вам нужно переопределить функцию как частную функцию.
Один из вариантов, который вы можете использовать, – это превратить создание экземпляра в функцию и предоставить соответствующие геттеры и сеттеры в конструкторе:
class Counter { let inc: () -> Int let dec: () -> Int init(start: Int) { var n = start inc = { ++n } dec = { --n } } } let c = Counter(start: 10) c.inc() // 11 c.inc() // 12 c.dec() // 11
Теперь в бета-версии 4 они добавили модификаторы доступа в Swift.
от Xcode 6 beta 4 realese отмечает :
Управление быстрым доступом имеет три уровня доступа:
private
объекты могут быть доступны только из исходного файла, где они определены.internal
объекты могут быть доступны в любом месте цели, где они определены.public
объекты могут быть доступны из любого места в пределах целевого объекта и из любого другого контекста, который импортирует модуль текущей цели.По умолчанию большинство объектов в исходном файле имеют внутренний доступ. Это позволяет разработчикам приложений в значительной степени игнорировать контроль доступа, позволяя разработчикам инфраструктуры полностью контролировать API-интерфейс инфраструктуры.
Языковая грамматика не имеет ключевых слов «публичный», «закрытый» или «защищенный». Это предполагает, что все будет общедоступным. Конечно, может быть какой-то альтернативный метод определения модификаторов доступа без этих ключевых слов, но я не смог найти его в языковой ссылке.
Swift 3 и 4 внесли много изменений и для уровней доступа переменных и методов. У Swift 3 и 4 теперь есть 4 разных уровня доступа, где открытый / общеansible доступ является наивысшим (наименее ограничительным) уровнем доступа, а частный доступ является самым низким (наиболее ограничительным) уровнем доступа:
- частные функции и члены могут быть доступны только из области самого объекта (struct, class, …) и его расширений (в Swift 3 также были ограничены расширения)
- Функции fileprivate и члены могут быть доступны только из исходного файла, где они объявлены.
- внутренние функции и члены (которые по умолчанию, если вы явно не добавляете ключевое слово уровня доступа), могут быть доступны в любом месте цели, где они определены. Вот почему TestTarget не имеет автоматического доступа ко всем источникам, они должны быть отмечены как доступные в инспекторе файлов xCode.
- открытые или публичные функции и члены могут быть доступны из любой точки цели и из любого другого контекста, который импортирует модуль текущей цели.
Интересно:
Вместо того, чтобы маркировать каждый отдельный метод или элемент как «частный», вы можете охватить некоторые методы (например, обычно вспомогательные функции) в расширении classа / структуры и пометить все расширение как «личное».
class foo { } private extension foo { func somePrivateHelperFunction01() { } func somePrivateHelperFunction02() { } func somePrivateHelperFunction03() { } }
Это может быть хорошей идеей, чтобы получить улучшенный код поддержки. И вы можете легко переключать (например, для модульного тестирования) на не-частные, просто изменяя одно слово.
Документация Apple
Надеюсь сэкономить время для тех, кто хочет что-то вроде защищенных методов:
В соответствии с другими ответами, swift теперь предоставляет «частный» модификатор, который определен скорее как файл, а не как class, например, в Java или C #. Это означает, что если вы хотите защищенные методы, вы можете сделать это с помощью быстрых частных методов, если они находятся в одном файле
- Создайте базовый class для хранения «защищенных» методов (фактически частных)
- Подclass этого classа для использования тех же методов
- В других файлах вы не можете получить доступ к методам базового classа, даже если вы подclassы либо
например, файл 1:
class BaseClass { private func protectedMethod() { } } class SubClass : BaseClass { func publicMethod() { self.protectedMethod() //this is ok as they are in same file } }
Файл 2:
func test() { var a = BaseClass() a.protectedMethod() //ERROR var b = SubClass() b.protectedMethod() //ERROR } class SubClass2 : BaseClass { func publicMethod() { self.protectedMethod() //ERROR }
}
STARTING SWIFT 2.2;)
- общественного
- внутренний
- Частный
По умолчанию Внутренний
до swift 2.0 было только три уровня доступа [Public, internal, private], но в swift 3.0 apple добавлен два новых уровня доступа, которые являются [Open, fileType], поэтому теперь в swift 3.0 есть 5 уровней доступа. Здесь я хочу очистить роль из этих двух уровней доступа 1. Open: это очень похоже на Public, но единственное различие заключается в том, что Public может получить доступ к подclassу и переопределить, а Открытый уровень доступа не может получить доступ к этому изображению, взятому с веб-сайта Medium, и это описывает разницу между открытым и общедоступным доступом
Теперь на второй новый уровень доступа 2. filetype – это более крупная версия частного или меньшего уровня доступа, чем внутренняя. FileType может получить доступ к расширенной части [class, struct, enum] и private, не может получить доступ к расширенной части кода, к которой он может получить доступ лексический масштаб этого изображения взят с веб-сайта Medium, и это описывает разницу между fileType и частным уровнем доступа