[Swift] 접근제어(Access Control)

728x90

접근제어(Access Control)

접근제어란 코드끼리 상호작용을 할 때 파일 간 또는 모듈 간에 접근을 제한할 수 있는 기능 입니다.

이런 접근제어가 왜 필요할까요?

객체지향 프로그래밍 패러다임에서 중요한 캡슐화와 은닉화를 구현하려면 외부에서 보이지 않거나 접근하지 말아야 할 코드가 있습니다. 불필요한 접근으로 의도치 않은 결과를 초래하거나 꼭 필요한 부분만 제공해야하는데 전체 코드가 노출될 가능 성이 있을 때 우리는 접근제어를 통해 우리가 의도한 대로 코드를 사용하는 프로그래머에게 코드를 작성 하도록 유도할 수 있습니다.

Swift접근 제어 모델은 모듈 소스파일의 개념을 기반으로 합니다.

 

모듈

  • import 를 통해 다른 모듈로부터 불러들일 수 있는 하나의 코드 묶음 단위
  • Library / Framework / Application 등

 

소스 파일 (Source File)

  • 모듈 내에 포함된 각각의 Swift 소스 코드 파일

 

Aceess Levels

Swift에서는 5가지의 다른 접근 레벨 제공합니다.

  • open(가장 개방적) -> public -> internal(Default) -> fileprivate -> private(가장 제한적)

 

Access Control Syntax

public class SomePublicClass1 {                // explicitly public class
  public var somePublicProperty = 0            // explicitly public class member
  var someInternalProperty = 0                 // implicitly internal class member, 클래스가 public 이여도 키워드로 쓰지 않으면 internal입니다.
  fileprivate func someFilePrivateMethod() {}  // explicitly file-private class member
  private func somePrivateMethod() {}          // explicitly private class member
}

class SomeInternalClass1 {                     // implicitly internal class
  public var somePublicProperty = 0           // 스코프의 범위가 가장 큰 클래스 범위가 internal이기때문에 public 변수가 있어도 접근을 못한다.
  var someInternalProperty = 0                 // implicitly internal class member
  fileprivate func someFilePrivateMethod() {}  // explicitly file-private class member
  private func somePrivateMethod() {}          // explicitly private class member
}

fileprivate class SomeFilePrivateClass1 {      // explicitly file-private class
  func someFilePrivateMethod() {}              // 스코프의 범위가 가장 큰 클래스 범위가 fileprivate이기 때문에 default로fileprivate 접근자이다. implicitly file-private class member
  private func somePrivateMethod() {}          // explicitly private class member
}

private class SomePrivateClass1 {              // explicitly private class
  func somePrivateMethod() {}                  // implicitly private class member
}

 

open, public

open, public키워드는 모듈 외부에서 접근이 가능하다는 공통점이 있고,
이 둘에는 다음과 같은 차이점이 존재합니다.

  • 모든 접근수준 중 open만이 모듈 밖의 다른 모듈에서 상속될 수 있습니다. (클래스)
  • 모든 접근수준 중 open으로 선언된 클래스의 멤버(프로퍼티, 메소드)들만이 다른 모듈에서 override될 수 있습니다.

예를 들어 iOS 프로젝트를 할 때 우리는 반드시 UIKit을 사용하게 됩니다. UIKit은 애플의 개발자들이 만들어 놓은 하나의 외부 모듈로 우리가 어플리케이션을 만들 때 우리의 프로젝트(모듈)에서 필수로 사용하는 외부모듈 중 하나입니다.
그리고 그 중 가장 우리에게 익숙한 UIViewController 클래스를 살펴보도록 하겠습니다.

open class UIViewController : UIResponder, NSCoding, UIAppearanceContainer, UITraitEnvironment, UIContentContainer, UIFocusEnvironment {

  public init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?)
  public init?(coder aDecoder: NSCoder)

  open var view: UIView!

  open func loadView()

	.
	.
	.
}

보시다시피 UIViewController는 open으로 선언되어 있습니다. 그렇기 때문에 우리는 우리의 프로젝트에서 UIViewController를 상속받는 여러 뷰 컨트롤러를 생성할 수 있습니다.
또한 UIViewController가 open으로 선언되어 있기 때문에 이를 상속받는 클래스에서 public으로 선언된 메소드들도 override할 수 있습니다.

 

internal

internal은 따로 접근제어를 선언해주지 않으면 기본으로 할당되는 접근제어 수준(defualt)입니다. internal은 같은 모듈 내에서는 어디서든 접근이 가능하고 클래스의 경우는 어느 곳에서도 해당 클래스를 상속받을 수 있습니다.

 

fileprivate

fileprivate는 하나의 스위프트 파일(.swift) 내부에서만 접근이 가능한 접근제어 수준입니다.
다른 언어에서는 하나의 파일에 하나의 클래스 혹은 하나의 타입만 정의하지만 스위프트에서는 종종 해당 타입과만 관련된 요소면 같은 파일 내에서 여러 타입을 정의하곤 합니다.
즉 하나의 타입에만 종속되어 사용되는 혹은 사용되어지는 타입은 같은 파일 내에 정의하고 접근제어를 fileprivate으로 선언하면 그 파일(.swift) 내부에서만 해당 타입에 접근이 가능합니다.

private

private는 그 요소가 선언된 영역(블록)내에서만 접근이 가능합니다.

 

private

private는 그 요소가 선언된 영역(블록)내에서만 접근이 가능합니다.

class SomePrivateClass {
  private var name = "name"
  private var age = 0
}

//에러 발생, name과 age에 접근을 하지 못함
//let somePrivateClass = SomePrivateClass()
//somePrivateClass.name
//somePrivateClass.age

위에 봤던 코드를 다시 보자면, 이런식의 결과를 나타낼수 있습니다.

public class SomePublicClass1 {                // explicitly public class
  public var somePublicProperty = 0            // explicitly public class member
  var someInternalProperty = 0                 // implicitly internal class member, 클래스가 public 이여도 키워드로 쓰지 않으면 internal입니다.
  fileprivate func someFilePrivateMethod() {}  // explicitly file-private class member
  private func somePrivateMethod() {}          // explicitly private class member
}

class SomeInternalClass1 {                     // implicitly internal class
  public var somePublicProperty = 0           // 스코프의 범위가 가장 큰 클래스 범위가 internal이기때문에 public 변수가 있어도 접근을 못한다.
  var someInternalProperty = 0                 // implicitly internal class member
  fileprivate func someFilePrivateMethod() {}  // explicitly file-private class member
  private func somePrivateMethod() {}          // explicitly private class member
}

fileprivate class SomeFilePrivateClass1 {      // explicitly file-private class
  func someFilePrivateMethod() {}              // 스코프의 범위가 가장 큰 클래스 범위가 fileprivate이기 때문에 default로fileprivate 접근자이다. implicitly file-private class member
  private func somePrivateMethod() {}          // explicitly private class member
}

private class SomePrivateClass1 {              // explicitly private class
  func somePrivateMethod() {}                  // implicitly private class member
}