Есть ли у 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 reference. Можно ли ограничить видимость данных в Swift?

17 ответов


по состоянию на Swift 3.0.1, есть 4 уровня доступа, описанный ниже от самого высокого (наименее ограничительного) до самого низкого (наиболее ограничительного).


1. open и public

включить объект для использования вне определяющего модуля (целевого объекта). Вы обычно используете open или public доступ при указании открытого интерфейса к фреймворку.

, open открыть применяется только к классам и их членам, и он отличается от public открыть следующим образом:
  • public классы и члены класса могут быть подклассами и переопределены только в пределах определяющего модуля (target).
  • open классы и члены класса могут быть подклассами и переопределены как внутри, так и вне определяющего модуля (цель.)

// 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

ограничивает использование entity к определяющему исходному файлу. Вы обычно используете fileprivate доступ, чтобы скрыть детали реализации определенной части функциональности, когда эти детали используются в пределах всего файла.

// First.framework – A.swift

internal struct A {

    fileprivate static let x: Int

}

A.x // ok

// First.framework – B.swift

A.x // 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
    }

}

A.x // error: x is unavailable

когда говорят о создании "частного метода" в Swift или ObjC (или ruby или java или...), эти методы не являются действительно частная. Вокруг них нет никакого контроля доступа. Любой язык, который предлагает даже небольшой самоанализ, позволяет разработчикам получать эти значения извне класса, если они действительно этого хотят.

Итак, то, о чем мы действительно говорим здесь,-это способ определить открытый интерфейс, который просто представлена функциональность, которую мы хотим чтобы, и "скрывает" остальное, что мы считаем "частным".

механизм 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)"
  }
}

помните, что протоколы являются первоклассными типами и могут использоваться в любом месте типа. и, при использовании таким образом, они предоставляют только свои собственные интерфейсы, а не те из типа реализации.

таким образом, пока вы используете MyClass вместо MyClassImplementation в типы параметров и т. д. он должны все просто работать:

func breakingAndEntering(foo:MyClass)->String{
  return foo.privateMethod()
  //ERROR: 'MyClass' does not have a member named 'privateMethod'
}

есть несколько случаев прямого назначения, когда вы должны быть явными с типом, а не полагаться на Swift, чтобы вывести его, но это вряд ли кажется прерывателем сделки:

var myClass:MyClass = MyClassImplementation()

использование протоколов таким образом является семантическим, достаточно кратким, и на мой взгляд, очень похоже на расширения класса, которые мы использовали для этой цели в ObjC.


насколько я могу судить, нет ключевых слов "public", "private" или "protected". Это предполагает, что все открыто.

однако Apple может ожидать, что люди будут использовать "протоколы" (называемые интерфейсами остальным миром) и дизайн завод шаблон чтобы скрыть детали реализации типа.

это часто хороший шаблон дизайна для использования в любом случае; как это позволяет изменить ваш реализация класс иерархия, сохраняя при этом логическое введите систему то же самое.


используя комбинацию протоколов, замыканий и вложенных/внутренних классов, можно использовать что-то по линиям шаблона модуля, чтобы скрыть информацию в 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 docs поэтому, если здесь есть недостаток, пожалуйста, укажите это, хотелось бы знать.


Swift 4

согласно упомянутому в Swift Документация-Контроль Доступа, Swift 4 и 5 Управление Доступом:

  • открыть и общественные: можно получить доступ из сущностей их модуля и сущностей любого модуля, который импортирует определяющий модуль.

  • внутренние: может только быть доступ из сущностей их модуля. Это уровень доступа по умолчанию.

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



в чем разница между открыть и public?

открыть это то же самое, что и public в предыдущие версии Swift, они позволяют классам из других модулей использовать и наследовать их, i.e: они могут быть подклассами из других модулей. Кроме того, они позволяют членам из других модулей использовать и переопределять их. Та же логика относится и к их модулям.

общественные разрешить классам из другого модуля использовать их, но не чтобы унаследовать их, я.e: они не может быть подклассом из других модулей. Кроме того, они позволяют членам из других модулей использовать их, но не для того, чтобы обойти. Для своих модулей они имеют одинаковую логику open (они позволяют классам использовать и наследовать их; они позволяют членам использовать и переопределять их).


в чем разница между fileprivate и частная?

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 контроля доступа?

как говорится в предложение 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 as fileprivate чтобы быть доступным во всем файле.

боковая панель Примечание: Если вы столкнулись с проблемами, связанными с не компиляцией Swift 4 с мигрировали старый проект Swift 3, Вы можете проверить это Q & A.


начиная с Xcode 6 beta 4, Swift имеет модификаторы доступа. Из примечаний к выпуску:

Swift access control имеет три уровня доступа:

  • частная объекты могут быть доступны только в исходном файле, где они определены.
  • внутренние сущности могут быть доступны в любом месте цели, где они определены.
  • общественные объекты могут быть доступны из в любом месте цели и из любого другого контекста, который импортирует модуль текущей цели.

неявным значением по умолчанию является internal, поэтому в целевом приложении вы можете оставить модификаторы доступа выключенными, за исключением тех случаев, когда вы хотите быть более ограничительными. В целевой структуре (например, если вы встраиваете фреймворк для совместного использования кода между приложением и общим доступом или расширением Today view) используйте public для обозначения API, который вы хотите предоставить клиентам вашего рамки.


Swift 3.0 обеспечивает пять различных элементов управления доступом:

  1. открыть
  2. общественные
  3. внутренние
  4. fileprivate
  5. частная

открыть открыть и public access позволяет использовать сущности в любом исходном файле из их определяющего модуля, а также в исходный файл из другого модуля, импортирующего определяющий модуль. Вы обычно используют открытые или публичный доступ при указании public интерфейс к фреймворку.

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

File-private access ограничивает использование сущности собственным исходным файлом определения. Использовать файл-Частный доступ чтобы скрыть детали реализации определенной части функциональности, когда те детали используются в пределах всего файла.

частная access ограничивает использование сущности вложенным объявлением. Используйте Частный доступ, чтобы скрыть детали реализации определенная часть функциональности, когда эти детали используются только в рамках одной декларации.

открыть доступ является самым высоким (наименее ограничительных) уровень доступа и частная доступ является самым низким (наиболее ограничительного) уровня доступа.

Уровни Доступа По Умолчанию

все сущности в коде (за некоторыми исключениями) имеют внутренний уровень доступа по умолчанию, если вы сами не задаете явный уровень доступа. В результате во многих случаях нет необходимости указывать явный уровень доступа в коде.

примечание к выпуску тема:

классы, объявленные как public, больше не могут быть подклассами вне их определяющий модуль и методы, объявленные как public, больше не могут быть переопределено вне их определяющего модуля. Разрешить классу быть внешний подкласс или метод для внешнего переопределения, declare они как открытые, что является новым уровнем доступа за пределами общественности. Импортированный Классы и методы Objective-C теперь импортируются как открытые чем публично. Модульные тесты, которые импорт модуля с помощью импорта @testable для подкласса публичных или внутренних классов как переопределить общедоступные или внутренние методы. (SE-0117)

больше информации и детали : Язык Программирования Swift (Управление Доступом)


нет, это невозможно. Нет никаких частных / защищенных методов и переменных вообще.

все общественные.


в бета-версии 6 в документации указано, что существует три разных модификатора доступа:

  • общественные
  • внутренние
  • частная

и эти три применяются к классам, протоколам, функциям и свойствам.

public var somePublicVariable = 0
internal let someInternalConstant = 0
private func somePrivateFunction() {}

для получения дополнительной информации проверьте Контроль Доступа.


механизмы управления доступом, как введено в Xcode 6:

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

  • открытый доступ позволяет сущностям использоваться в любом исходном файле из их определяющего модуля, а также в исходном файле из другой модуль, импортирующий определяющий модуль. Как правило, при указании открытого интерфейса для платформы используется открытый доступ.
  • внутренний доступ позволяет сущностям использоваться в любом исходном файле из их определяющего модуля, но не в любом исходном файле вне этого модуля. Обычно при определении внутренней структуры приложения или платформы используется внутренний доступ.
  • Частный доступ ограничивает использование объекта свой собственный определяющий исходный файл. Используйте Частный доступ, чтобы скрыть детали реализации определенной части функциональности.

публичный доступ-это самый высокий (наименее ограничительный) уровень доступа, а частный доступ-самый низкий (или самый ограничительный) уровень доступа.

по умолчанию accecss это внутренние, и как таковой не нужно указывать. Также обратите внимание, что частная описатель делает не работа над классом уровень, но на уровне исходного файла. Это означает, что для того, чтобы получить части класса действительно частные, вам нужно разделиться на собственный файл. Это также вводит некоторые интересные случаи в отношении модульного тестирования...

еще один момент для меня, который прокомментирован в ссылке выше, заключается в том, что вы не можете "обновить" уровень доступа. Если вы подкласс что-то, вы можете ограничить его больше, но не наоборот.

этот последний бит также влияет на функции, кортежи и конечно, другие вещи в том, что если т. е. функция использует частная класс, тогда недопустимо иметь функцию внутренние или общественные, так как у них нет доступа к частная класса. Это приводит к предупреждению компилятора, и вам нужно повторно объявить функцию как частная


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

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 Примечания:

Swift access control имеет три уровня доступа:

  • private объекты могут быть доступны только в исходном файле, где они определены.
  • internal сущности могут быть доступны в любом месте цели, где они определены.
  • public объекты могут быть доступны из в любом месте в пределах цели и из любого другого контекста это импортирует модуль текущей цели.

по умолчанию большинство сущностей в исходном файле имеют внутренний доступ. Это позволяет разработчикам приложений в значительной степени игнорировать контроль доступа, позволяя разработчикам framework полный контроль над в API фреймворка.


на язык грамматика не имеет ключевых слов "public", "private" или "protected". Это предполагает, что все открыто. Конечно, может быть какой-то альтернативный метод указания модификаторов доступа без этих ключевых слов, но я не мог найти его в языковой ссылке.


Swift 3 и 4 принес немало изменений и для уровней доступа переменных и методов. Swift 3 и 4 теперь имеет 4 различных уровня доступа, где открыть/общественная доступ является самым высоким (наименее ограничительного) уровня доступа и частная доступ является самым низким (наиболее строгие) уровень доступа:

  • частная функции и члены могут быть доступны только в рамках самой организации (struct, class,...) и его расширения (в Swift 3 также были ограничены расширения)
  • fileprivate функции и члены могут быть доступны только из исходного файла, где они объявлены.
  • внутренние функции и члены (по умолчанию, если вы явно не добавляете ключевое слово уровня доступа) могут быть доступны в любом месте цели, где они определены. Вот почему TestTarget не имеет автоматически доступ ко всем источникам, они должны быть отмечены как доступные в инспекторе файлов xCode.
  • open или public функции и члены могут быть доступны из любого места в целевом объекте и из любого другого контекста, который импортирует модуль текущего целевого объекта.

интересно:

вместо того, чтобы отмечать каждый метод или элемент как "частный" , вы можете охватить некоторые методы (например, обычно вспомогательные функции) в расширении a class / struct и отметьте все расширение как "Private".

class foo { }

private extension foo {
    func somePrivateHelperFunction01() { }
    func somePrivateHelperFunction02() { }
    func somePrivateHelperFunction03() { }
}

Это может быть хорошей идеей, чтобы получить лучший поддерживаемый код. И вы можете легко переключиться (например, для модульного тестирования) на non-private, просто изменив одно слово.

документация Apple


надеюсь, чтобы сэкономить время для тех, кто хочет что-то сродни защищенным методам:

согласно другим ответам, swift теперь предоставляет модификатор "private", который определяется по файлу, а не по классу, например, в Java или C#. Это означает, что если вам нужны защищенные методы, вы можете сделать это с помощью swift private methods если они находятся в одном файле

  1. создайте базовый класс для хранения "защищенных" методов (на самом деле рядовой)
  2. подкласс этот класс использовать те же методы
  3. в других файлах вы не можете получить доступ к методам базового класса, даже если вы подкласс либо

например, файл 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
    }

}


https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/AccessControl.html#//apple_ref/doc/uid/TP40014097-CH41-ID3

ЗАПУСК SWIFT 2.2;)

  • общественные
  • внутренние
  • частная

по умолчанию внутренний


до swift 2.0 было только три уровня доступа [Public, internal, private] но в swift 3.0 apple добавила два новых уровня доступа, которые являются [ Open, fileType] так теперь в swift 3.0 есть 5 уровней доступа Здесь я хочу прояснить роль этих двух уровней доступа 1. Open: это очень похоже на Public, но единственная разница в том, что общественность может получить доступ к подклассу и переопределить, и уровень открытого доступа не может получить доступ к этому Это изображение взято с Среднего веб-сайта, и это опишите разницу между открытым и открытым доступом

теперь второй новый уровень доступа 2. filetype-это большая версия частного или меньшего уровня доступа, чем внутренний Тип файла может получить доступ к расширенной части [class, struct, enum] и частный не может получить доступ к расширенной части кода, он может получить доступ только к лексическая область это изображение взято с Среднего веб-сайта, и это описывает разницу между типом файла и частным доступом уровень