class SomeClass {
private var name = "이름" // 내부적으로만 사용하겠다고 제한
func nameChange(name: String) {
if name == "길동" {
return // 어떤 로직을 넣을 수도 있음
}
self.name = name
}
}
let object1 = SomeClass()
//object1.name
//object1.name = "홍길동"
//object1.name
// 이름을 바꾸려면 특정 메서드로 실행만 가능
object1.nameChange(name: "민영")
open - 다른 모듈에서도 접근가능 / 상속 및 재정의도 가능 (제한 낮음)
public - 다른 모듈에서도 접근가능(상속/재정의불가)
internal - 같은 모듈 내에서만 접근가능(디폴트)
fileprivate - 같은 파일 내에서만 접근가능
private - 같은 scope내에서만 접근가능 (제한 높음)
모듈(module): 프레임워크, 라이브러리, 앱 등 import해서 사용할 수 있는 외부의 코드
따로 명시하지 않으면 internal 설정임(디폴트)
모듈(프레임워크나 라이브러리)을 만들어서 배포하려면, public이상으로 선언해야함
타입(클래스/구조체/열거형/스위프트 기본타입 등)
변수/속성
함수/메서드(생성자, 서브스크립트 포함)
프로토콜도 특정영역으로 제한될 수 있음
클래스의 접근수준을 가장 넓히면 - open / 구조체 - public
클래스 - open (상속, 재정의와 관계)
구조체 - public (구조체는 어짜피 상속이 없기 때문)
타입은 타입을 사용하는 변수(속성)나, 함수(메서드)보다 높은 수준으로 선언되어야함
// 변수
// public variable에 속한 타입은 더 낮은 접근 수준을 가지지 못함
// (public/internal/fileprivate/private)
var some: String = "접근가능"
// 함수
// 파라미터, 리턴 타입이 더 낮은 접근 수준을 가지지 못함
// (internal/fileprivate/private)
internal func someFunction(a: Int) -> Bool {
print(a) // Int 타입
print("hello") // String 타입
return true // Bool 타입
}
// 자신보다 내부에서 더 낮은 타입을 사용하면 접근을 못해서, 사용하지 못할 수 있음
// 타입
public class SomePublicClass {}
internal class SomeInternalClass {}
fileprivate class SomeFilePrivateClass {}
private class SomePrivateClass {}
// 변수 / 함수
public var somePublicVariable = 0
internal let someInternalConstant = 0
fileprivate func someFilePrivateFunction() {}
private func somePrivateFunction() {}
// 아무것도 붙이지 않으면?
class SomeInternalClass1 {} // 암시적인 internal 선언
let someInternalConstant1 = 0
// 실제 프로젝트에서 많이 사용하는 관습적인 패턴
// 속성(변수)를 선언시 private으로 외부에 감추려는 속성은 _(언더바)를 사용해서 이름 지음
class SomeOtherClass {
private var _name = "이름" // 쓰기 - private
var name: String { // 읽기 - internal
return _name
}
}
// 저장속성의 (외부에서) 쓰기를 제한하기 ⭐️
class SomeAnotherClass {
private(set) var name = "이름" // 읽기 - internal / 쓰기 - private
}
public class SomePublicClass { // 명시적인 public 선언
open var someOpenProperty = "SomeOpen" // open 이라고 설정해도 public으로 작동 ⭐️
public var somePublicProperty = "SomePublic"
var someInternalProperty = "SomeInternal" // 원래의 기본 수준
fileprivate var someFilePrivateProperty = "SomeFilePrivate"
private var somePrivateProperty = "SomePrivate"
}
let somePublic = SomePublicClass()
somePublic.someOpenProperty
somePublic.somePublicProperty
somePublic.someInternalProperty
somePublic.someFilePrivateProperty // 같은 파일 안이기 때문에 접근 가능
//somePublic.somePrivateProperty
open class SomeClass {
var someProperty = "SomeInternal"
// internal 임 ➞ 클래스와 동일한 수준을 유지하려면 명시적으로 open선언 필요
}
public class A {
fileprivate func someMethod() {}
}
// public이하의 접근 수준만 가능(public/internal/fileprivate)
internal class B: A {
override internal func someMethod() { // 접근 수준 올려서 재정의 가능 ⭐️
super.someMethod() // (더 낮아도) 모듈에서 접근가능하기 때문에 호출가능
}
}
public class SomeClass {
private var somePrivateProperty = "somePrivate"
}
extension SomeClass { // public으로 선언한 것과 같음
func somePrivateControlFunction() {
somePrivateProperty = "접근가능"
}
}
struct TrackedString {
//var numberOfEdits = 0 // 외부에서도 변경가능
//private var numberOfEdits = 0 // 이렇게 선언하면, 읽기도 불가능해짐
private(set) var numberOfEdits = 0 // setter에 대해서만 private 선언 ⭐️
//internal private(set) var numberOfEdits = 0
// 속성 관찰자
var value: String = "시작" {
didSet {
numberOfEdits += 1
}
}
}
var stringToEdit = TrackedString()
stringToEdit.value = "첫설정"
stringToEdit.value += " 추가하기1"
stringToEdit.value += " 추가하기2"
stringToEdit.value += " 추가하기3"
print("수정한 횟수: \(stringToEdit.numberOfEdits)")
print(stringToEdit.value)
// 외부에서 직접설정하는 것은 불가능 (읽는 것은 가능) ⭐️
//stringToEdit.numberOfEdits = 3