23-2. 타입, 프로퍼티별 접근 제어

🌈 devleeky16498·2022년 4월 24일
0

사용자 정의 타입(custom types)

  1. 사용자 정의 타입에 명시적 접근 수준을 지정하고 싶다면, 타입 정의 간 지정한다. 그러면 새로운 타입의 접근 수준이 허용하는 범위 내 해당 타입을 사용 가능하다. 예를 들어서 file-private클래스를 정의하면 해당 클래스는 file-private클래스가 정의된 소스파일에 프로퍼티 타입 또는 함수의 파라미터, 반환타입으로만 사용될 수 있다.
  2. 타입의 접근 수준은 해당 타입의 멤버(프로퍼티, 메서드, 초기화 구문, 서브 스크립트)의 기본 접근 수준에도 영향을 미친다. 타입의 접근 수준을 private으로 정의하면 멤버들의 기본 접근 수준도 private이 된다.
public class SomePublicClass {
	public var somePublicProperty = 0
    //class member
    var someInternalProperty = 0
    //암시적으로 internal
    fileprivate func someFilePrivateMethod() {}
    //명시적으로 fileprivate
    private func somePrivateMethod() {}
    //명시적인 private
}

class SomeInternalClass {
    //암시적으로 Internal
	var someProperty = 0
    //암시적으로 Internal
        fileprivate func someFilePrivateMethod() {}
    //명시적으로 fileprivate
}

fileprivate class someFilePrivateClass {
	//암시적으로 fileprivate
	var someProperty = 0
    //암시적으로 fileprivate
     private func someFilePrivateMethod() {}
    //명시적으로 private
}

//위에서 보여주는 것은 public인 경우 암시적 접근 수준은 모두 Internal값을 따른다.
//하지만 Internal보다 낮은 수준의 보다 폐쇄적인 접근 수준에서는 가장 상위인 타입의 접근 수준을 암시적으로 따르게 된다.

튜플 타입(Tuple)

  1. 튜플 타입에 대한 접근 수준은 해당 튜플에서 사용되는 모든 타입에 가장 제한적 접근 수준이다. 하나는 internal, 하나는 private이라면, 전체적 접근 수준은 private이다.
  2. 튜플은 클래스, 구조체, 열거형, 함수와 같이 독립형 정의가 없으므로 이 접근 수준은 튜플 타입을 구성하는 타입에서 자동으로 결정되고 명시적으로 지정 가능하다.

함수 타입(Function)

  1. 함수 타입에 대한 접근 수준은 함수의 파라미터 타입과 반환 타입 중 가장 제한적 접근 수준으로 계산된다. 파라미터 타입이 internal, 반환 타입이 private이라면 이는 private수준을 가진다. 파라미터가 더 폐쇄적이고 반환타입이 개방적인 경우도 마찬가지로 적용된다.
private func someFunction() -> (SomeInternalClass, SomePrivateClass) {
	//함수 내용
}
//다음과 같은 경우 반환 값에서 가장 폐쇄적 수준인 private 타입을 반환하므로 함수를 명시적으로 private이라고 해줘야 유효한 함수이다.

열거형 타입(Enumeration)

  1. 열거형이 가지는 각 케이스들은 열거형과 같은 수준을 자동으로 물려받는다. 또한 개별 열거형 케이스에 대한 접근 수준을 지정할 수 없다.
public enum CompassPoint {
	case north
    case south
    case east
    case west
}
//다음과 같은 경우 열거형 안의 4개 케이스는 모두 public 접근 수준을 지니게 된다.
  1. 원시값(rawvalue)과 연관된 값(associated value)타입은 열거형 접근 수준보다 높은 수준이어야 한다. internal접근 수준의 열거형 원시값 타입으로 private을 사용할 수 없다.
    반면 public은 사용이 가능하다.

중첩된 타입(Nested type)

  1. 중첩된 타입의 접근 수준은 포함한 타입이 public이 아닌 경우 포함한 타입과 동일하다. public타입 내의 중첩된 타입은 자동으로 internal을 가지게 된다.
  2. public접근 수준을 가진 타입 내 중첩된 타입이 internal이 아닌 public 접근 수준을 가지려면, 명시적으로 public으로 중첩된 타입을 선언해주어야 한다.

서브클래싱(Subclassing)

  1. 하위 클래스는 상위 클래스보다 더 높은 접근 수준을 가질 수 없다. 예를 들어서 internal상위 클래스에 public 하위 클래스를 작성할 수 없다.
  2. 하위클래스가 상위클래스를 상속할 때 접근 수준을 재정의(overriding) 해줄 수 있다.
public class A {
	fileprivate func someMethod() {
    	//메서드 내용
    }
}

internal class B : A {
	override internal func someMethod() {
    	//재정의 내용
    }
}
//핵심은, 하위 클래스가 상속을 받으면서 하위 클래스의 접근수준을 벗어나지 않는 범위 내
//상위 클래스 메서드의 접근 수준을 재정의 가능하다.

public class A {
	fileprivate func someMethod() {
    	//메서드 내용
    }
}

internal class B : A {
	override internal func someMethod() {
    	super.someMethod()
    }
}
//상위 클래스의 메서드가 재정의 간의 접근 수준 계층을 준수하는 경우,
//정상적으로 호출 후 사용이 가능하다.

상수, 변수, 프로퍼티 및 서브 스크립트

  1. 상수, 변수 또는 프로퍼티는 타입보다 더 열린 접근 수준을 가질 수 없다. private타입 안에서 public 프로퍼티를 작성할 수 없다.
  2. 이들은 private타입을 사용시 명시적으로 표시해주어야 한다.
private var privateInstance = SomePrivateClass()
//다음과 같이 명시적으로 작성해준다.

Getter와 Setter

  1. 위의 프로퍼티 감시자는 속해있는 상수, 변수, 프로퍼티 및 서브스크립트에 대한 접근 수준을 인수한다.
  2. 해당 읽기 및 쓰기 범위를 제한하기 위해서 getter보다 낮은 접근 수준으로 setter 제공이 가능하다. var전에 private(set), fileprivate(set)등의 키워드를 통해서 더 낮은 접근 수준을 할당한다.
struct TrackedString {
	private(set) var numberOfEdits = 0
    var value : String = "" {
    	didSet {
        	numberOfEdits += 1
        }
    }
}
//여기에서 구조체와 value는 명시적으로 접근 수준을 제공하지 않았으므로, internal의 접근 수준을 가진다.
//numberOfEdits에 대한 접근 수준은 프로퍼티의 getter는 internal을 가지지만, 프로퍼티는 TrankcedString 구조체 부분의 코드 내에서만 수정이 가능하도록 하기 위해서 private(set) 수식어로 표기한 상태이다.
//이렇게 되면 구조체 외부에서는 읽기 전용으로 구조체 내에서는 내부적 수정이 가능하다.

초기화 구문(initializer)

  1. 사용자 정의 초기화 구문은 초기화 하는 타입보다 더 낮거나 같은 수준으로 할당이 가능하다. 유일한 예외는 필수 초기화 구문이다. 필수 초기화 구문은 자신이 속한 클래스와 동일한 접근 수준을 가져야 한다.
  2. 기본 초기화 구문은 타입이 public으로 정의 되지 않는 이상 초기화 하는 타입과 같은 접근 수준을 가진다.
  3. 구조체의 모든 저장된 프로퍼티가 private이라면 구조체 타입의 기본 멤버별 초기화 구문은 private이라고 간주한다. 마찬가지로 저장된 프로퍼티가 fileprivate이라면 fileprivate을 가진다고 간주한다. 위 기본 초기화 구문과 마찾가지로, Public 구조체 타입은 타입의 정의 부분으로 public멤버별 초기화 구문을 자체적으로 제공해야 한다.

프로토콜(Protocol)

  1. 프로토콜 타입에 명시적 접근 수준을 할당하려면 프로토콜 정의 시점에서 지정하면 된다.
  2. 프로토콜 정의 내 각 요구사항의 접근 수준은 자동으로 프로토콜과 같은 수준으로 지정된다.
  3. 타입과 다르게, public 프로토콜을 정의하면 요구사항은 구현이 전부 public수준을 요구한다. 이는 타입이 public이더라도 명시적이지 않은 경우는 internal로 설정되는 것과 차이가 있다.
  4. 프로토콜을 상속하는 새로운 프로토콜은 상속받은 프로토콜과 최대 동일한 접근 수준을 가질 수 있다. internal프로토콜을 상속하면 public을 작성 불가하다.

확장(extension)

  1. 확장에 추가된 모든 타입의 멤버는 기존 타입에 선언된 타입의 멤버와 같인 기본 접근수준을 가진다. public 또는 internal 타입으로 확장하면 추가한 모든 타입 멤버는 internal을 가진다.
  2. 확장 내에서 정의된 모든 멤버에 대해 새로운 접근 수준을 할당하기 위해서 private과 같이 명시적으로 접근 수준 수식어를 줄 수 있다. 또한 확장 내에서 개별 타입 멤버를 다시 정의하는 것도 가능하다.

제네릭(generic)과 타입 별칭

  1. 제네릭 타입 또는 함수에 대한 접근 수준은 제네릭 타입 또는 함수 자체의 접근 수준과 해당 타입 파라미터에 대한 모든 타입의 제약조건의 최소 수준이다.
  2. 타입 별칭은 별칭이 지정된 타입의 접근수준보다 작거나 같은 수준을 가질 수 있다. 이는 프로토콜의 타입별칭 또한 마찬가지 이다.
profile
Welcome to Growing iOS developer's Blog! Enjoy!🔥

0개의 댓글