Notice
Recent Posts
Recent Comments
Link
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
Archives
Today
Total
관리 메뉴

브래의 슬기로운 코딩 생활

8 - extension, Swift 접근 제어 (access control, access modifier), 프로토콜(protocol)과 Delegate, 열거형 (enum) 본문

2 - 겨울방학/Swift 복습

8 - extension, Swift 접근 제어 (access control, access modifier), 프로토콜(protocol)과 Delegate, 열거형 (enum)

김브래 2023. 12. 28. 19:07

Human Interface Guidelines


extension(익스텐션)


extension

- class, struct, enum, protocol에 새로운 기능을 추가
- extension 하위 클래스를 생성하거나 참조하지 않고 기존 클래스에 메서드, 생성자(initializer), 계산 프로퍼티 등의 기능을 추가하기 위하여 사용
- Swift의 built-in클래스와 iOS 프레임워크에 내장된 클래스에 기능을 추가할 때, extension을 이용하면 매우 효과적임
- 클래스(구조체, 열거형, protocol)는 다음과 같은 형태로 확장(익스텐션)함
 

extension 기존타입이름 {

  // 새로운 기능

}

 

표준 자료형 Double 구조체에 두 배의 값을 반환하는 프로퍼티를 추가

extension Double {

  var squared : Double { //기존 Double 구조체에 계산 프로퍼티 추가

    return self * self

  }

}

 

이제는 Double형의 인스턴스 myValue를 다음과 같이 사용할 수 있음

let myValue: Double = 3.0
print(myValue.squared)  // 9.0
print(2.0.squared)   //Double형 값에도 .으로 바로 사용 가능, 4.0
 

extension은 protocol 채택할 때 소스를 깔끔하게 분할하기 위해 많이 사용

 

- 아래처럼 소스를 작성하면 클래스가 너무 비대해짐
class ViewController: UIViewController, UIPickerViewDelegate, 
UIPickerViewDataSource{}


- 클래스를 다음과 같이 나누면 소스가 깔끔하고 이해하기 쉬움
class ViewController: UIViewController{}
extension ViewController: UIPickerViewDelegate{}
extension ViewController: UIPickerViewDataSource{}


Swift 접근 제어 (access control, access modifier)


 access modifier(or access specifiers)

접근 속성(접근 수정자, 액세스 수정자, 액세스 지정자 )는 클래스, 메서드, 멤버의 접근 가능성을 설정하는 객체 지향 언어의 키워드
 
 
구성 요소를 캡슐화 하는 데 사용 
 
노란 색은 언어별 디폴트 접근 속성

Swift의 access control

public class MyClass{

 // 모듈의 모든 소스 파일 내에서 접근 + 정의한 모듈을 가져오는 다른 모듈의 소스파일에서도 접근 가능

    fileprivate var name : String = "Kim"

   //현재 소스 파일 내에서만 사용 가능

    private func play() {}

   //현재 블럭 내에서만 사용 가능

    func display(){} //internal은 디폴트 속성으로 생략됨

   //해당 모듈의 모든 소스 파일 내에서 사용

}


접근 제어

접근 제어를 생략하면 internal이 기본

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() {}

모듈은 코드 배포(code distribution)의 단일 유닛
- 앱, Framework(UIKit ),외부라이브러리
- import Alamofire
open 접근 및 public 접근을 통해 모듈의 모든 소스 파일 내에서 사용할 수 있으며, 정의한 모듈을 가져오는 다른 모듈의 소스파일에서도 사용할 수 있다. 일반적으로 Framework에 공용 인터페이스를 지정할 때는 open 또는 public 접근을 사용한다.
open 접근은 클래스 및 클래스 멤버에만 적용
internal 접근은 해당 모듈의 모든 소스 파일 내에서 사용되지만, 해당 모듈 외부의 소스파일에서는 사용되지 않도록 한. 일반적으로 App이나  Framework의 내부 구조를 정의할 때 internal 접근을 사용한다.
fileprivate 접근은 해당 소스 파일 내에서만 사용가능
private접근은 블록과 동일한 파일에 있는 해당 선언의 extension으로 제한한다.

접근 제어 예

open class var blue : UIColor { get }
- open : 모듈 외부까지(클래스에만 사용) 접근 가능
- class : 클래스 프로퍼티
- 읽기 쓰기 가능한 프로퍼티는 정의 뒤에 {get set}
- 읽기만 가능한 프로퍼티는 정의 뒤에 {get}

프로토콜(protocol)과 Delegate


프로토콜(protocol)

특정 클래스와 관련없는 함수(메서드)들의 선언 집합
- 함수(메서드) 정의는 없음
- 기능이나 속성에 대한 설계도
자바, C#의 interface
C++의 abstract base class
Protocol Oriented Programming(POP)
- 프로토콜 단위로 묶어 표현하고, extension으로 기본적인 것을 구현(protocol default implementation)을 해서 단일 상속의 한계를 극복

protocol 정의

protocol 프로토콜명{

   프로퍼티명

   메서드 선언 //메서드는 선언만 있음

}

protocol 프로토콜명 : 부모1프로토콜, 부모2프로토콜{

   // 프로토콜은 다중 상속도 가능

}


protocol과 프로퍼티/메서드 선언

protocol SomeProtocol {

    var x: Int { get set }  //읽기와 쓰기가 가능

    var y: Int { get }  //읽기 전용

    static var tx: Int { get set }

    static func typeMethod()

    func random() -> Double

}


protocol 정의, 채택, 준수

protocol Runnable {    //대리하고 싶은 함수 목록 작성

  var x : Int {get set} //읽기와 쓰기 가능 프로퍼티,{get}은 읽기 전용

  //property in protocol must have explicit { get } or { get set } specifier

  func run()  //메서드는 선언만 있음

}

 

class Man : Runnable {    //채택, adopt

  var x : Int = 1   //준수, conform

  func run(){print("달린다~")}    //준수, conform 

}


delegate

대표자(명사)
위임하다(동사)


Delegation

Delegation(위임)은 클래스나 구조체가 일부 책임을 다른 유형의 인스턴스로 전달 (또는 위임 )할 수 있도록 하는 디자인 패턴이다. 
위임된 기능은 프로토콜에서 정의하며, delegate가 위임된 기능을 제공한다. 
위임은 특정 작업에 응답하거나 외부에서 데이터를 가져오는데 사용할 수 있다.

delegate

대리자, 조력자
이런 일이 있을 때 delegate 너가 좀 전담해줘
- 델리게이트로 선언된 (보통 내가 만든 클래스의) 객체는 자신을 임명한 객체(테이블뷰, 피커뷰 등)가 일을 도와달라고 하면 지정된 메서드를 통하여 처리해 줌
델리게이트 패턴
- 하나의 객체가 모든 일을 처리하는 것이 아니라 처리 해야 할 일 중 일부를 다른 객체에 넘기는 것

보통 프로토콜을 사용


열거형 (enum)


열거형(enum)

관련있는 데이터들이 멤버로 구성되어 있는 자료형 객체
- 원치 않는 값이 잘못 입력되는 것 방지
- 입력 받을 값이 한정되어 있을 때
- 특정 값 중 하나만 선택하게 할 때
색깔
- 빨강, 녹색, 파랑

 

성별
- 남, 여

열거형 정의

enum 열거형명{

      열거형 정의

   }

 

enum Planet {

     case Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune

  }   //하나의 case문에 멤버들 나열하는 것도 가능
 
 

enum Compass {
    case North
    case South
    case East
    case West
  }


print(Compass.North)  //열거형명.멤버, North
var direction = Compass.West
direction = .East //두번째 부터는 열거형명 생략 가능
print(direction, type(of:direction)) // East Compass


문맥에서 타입의 추론이 가능한 시점 (등호 좌변의 변수 타입이 확정적일 때)에는 열거형명 생략 가능

열거형 멤버별 기능 정의

enum Compass {

    case North

    case South

    case East

    case West

  }

 

var direction : Compass

direction = .South

 

switch direction {

case .North:

    print("북")

case .South:

    print("남")

case .East:

    print("동")

case .West:

    print("서")

}


열거형 예제

스와이프(swipe) 제스처는 UISwipeGestureRecognizer 클래스로 인식
특정 방향으로의 스와이프는 다음 상수를 클래스의 direction 프로퍼티에 할당하여 인식
- UISwipeGestureRecognizerDirection.right
- UISwipeGestureRecognizerDirection.left
- UISwipeGestureRecognizerDirection.up

 

- UISwipeGestureRecognizerDirection.down
 
.right, .left, .up, .down으로 축약해서 쓸 수 있음
설정된 방향이 없다면 기본 설정은 오른쪽 스와이프를 인식
UISwipeGestureRecognizer 인스턴스를 위쪽 스와이프에 대해 인식하도록 설정