💡 코드의 세부 구현 내용을 숨기는 것이 가능하도록 만드는 개념으로, 객체지향의 은닉화가 가능해진다.
classSomeClass {privatevar name ="soi"funcchangeName(name: String) {if name =="ios" { return } self.name = name }}let object1 =SomeClass()object.name ="ios"
타 개발자가 잘못 사용할 수 있는 경우를 제한할 수 있다.
Swift의 접근 수준(Access Levels)
open : 다른 모듈에서 접근 가능, 상속 및 재정의 가능
public : 다른 모듈에서 접근 가능, 상속 및 재정의 불가능
internal : Default 수준, 같은 모듈 내에서 접근 가능
fileprivate : 같은 파일 내에서만 접근 가능
private : 같은 scope 내에서 접근 가능
💡 모듈이란?
import 해서 사용할 수 있는 외부 코드라고 생각하자.
개발자가 만든 모든 코드로, 하나의 단위를 의미한다.
Foundation도 framework지만, 하나의 모듈로 볼 수 있다.
즉, framework나 라이브러리, 또는 내가 만든 코드!
만약, 모듈을 만들어 배포하고자 한다면, public 이상으로 선언되어야한다.
접근 제어를 가질 수 있는 요소 (엔티티 / 독립된 객체)
타입 ( 클래스, 구조체, 열거형 등 Swift 기본 타입)
구조체가 가질 수 있는 가장 넓은 제한 수준은 public이다. (상속이 없기 때문에)
타입 자체도 접근 제어 수준을 가질 수 있다.
변수 / 속성
함수 / 메서드 (생성자, 서브스크립트 포함)
프로토콜 (특정 영역으로 제한)
접근제어가 필요한 이유
정보의 은닉화가 가능하다.
외부에서 private으로 선언된 속성, 메서드에 접근이 불가능하다. 이에 코드 내부의 세부 구현 내용을 숨기는 것이 가능하다.
애플이 자신들이 원하는 코드를 감출 수 있다.
코드의 영역을 분리시켜 효율적인 관리가 가능하다.
컴파일 시간이 줄어든다.
타입이 오픈되어있다면, 모든 곳에서 사용할 수 있어야하므로 오래걸린다.
접근제어를 사용하면 해당 변수가 어떤 범위에서 적용되는지 확실히 알 수 있기 때문이다.
원칙
💡 타입은 타입을 사용하는 변수(속성)나, 함수보다 높은 수준으로 선언되어야한다!
// 변수//public variable에 속한 타입은 더 낮은 접근 수준을 가질 수 없다.//(internal, fileprivate, privae)var some: String="hello"//함수// 파라미터, 리턴 ㅇ타입이 더 낮은 접근 수준을 가지지 못함// internal, fileprivate, privateinternalfuncsomeFunction(a: Int) ->Bool {print(a)returntrue}// 자신보다 내부에서 더 낮은 타입을 사용하면 접근을 못해서 사용하지 못할 수도 있다.
변수와 타입 모두 접근 수준이 설정되어있음
변수는 internal, 타입은 public이 기본 설정!
함수도 마찬가지
함수 internal, 파라미터, 리턴형은 public
실무에서 사용하는 관습적 패턴
실제 프로젝트에서 많이 사용하는 관습적 패턴
언더바를 붙인 속성 이름은 언더바를 사용해서 이름을 짓는다. (c언어)
classSomeOtherClass {privatevar**_name**="name"// 쓰기 - privatevar**name**:String { // 읽기 - internalreturn _name }funcchangeName(name: String) { // 이렇게 수정도 가능하기 ㄴ함! self._name = name }}
setter의 제한을 높이는 방법 (접근 수준 낮추기)
classSomeClass {privatevar _name ="이름"var name: String {return _name }}classSomeAnotherClass {internalprivate(set)var name ="이름"// 읽기 - internal / 쓰기 - private, internal은 생략가능}let a =someAnotherClass()a.name // 접근 가능a.name ="hello"// 불가능, private이므로
Swift에서 사용할 수 있는 키워드!
classSomeAnotherClass {private(set)var name ="이름"// 읽기 - internal / 쓰기 - private}let ab =SomeAnotherClass()ab.name // 가능 ab.name ="길동 // error, 애는 private
커스텁 정의 타입의 접근 제어
💡 1. 타입의 내부 멤버는 타입 자체의 접근 수준을넘을 수 없다.
⇒ 타입의 접근 제어 수준은, 해당 타입 멤버의 접근 제어 수준에 영향을 미친다.
내부 멤버가 명시적 선언을 하지 않는다면, Internal로 유지된다.
⇒ 타입의 접근수준이 높다고, 내부 멤버의 접근 수준이 무조건 높아지는 것은 아니다.
// 타입의 접근 제어 수준은 (해당 타입)멤버의 접근 제어 수준에 영향을 미침// (예시) 타입이 internal 로 선언 되면 내부의 멤버는 internal이하(internal / fileprivate / private)로 설정됨publicclassSomePublicClass { // 명시적인 public 선언openvar someOpenProperty ="SomeOpen"// open 이라고 설정해도 public으로 작동 ⭐️publicvar somePublicProperty ="SomePublic"var someInternalProperty ="SomeInternal"// 원래의 기본 수준fileprivatevar someFilePrivateProperty ="SomeFilePrivate"privatevar somePrivateProperty ="SomePrivate"}let somePublic =SomePublicClass()somePublic.someOpenPropertysomePublic.somePublicPropertysomePublic.someInternalPropertysomePublic.someFilePrivateProperty // 같은 파일 안이기 때문에 접근 가능//somePublic.somePrivateProperty
💡 1. 타입 : 상속해서 만든 서브클래스는, 상위클래스보다 더 높은 접근 수준을 가질 수 없다. 2. 멤버 : 동일 모듈에서 정의한 클래스의 상위 멤버에 접근 가능하다면, 접근 수준을 높여서 재정의 할 수 있다.
publicclassA {fileprivatefuncsomeMethod() { }}// public 이하의 접근수준만 가질 수 있다.internalclassB:A {overrideinternalfuncsomeMethod() { // 접근 수준을 올려서 재정의 super.someMethod()// 접근 수준이 더 낮아도, 모듈에서 접근 가능하므로 호출 가능. }}