티스토리 뷰

반응형

안녕하세요 Pingu입니다.🐧

 

지난 글에 이어 오늘도 Object Oriented Programming, OOP라고 불리는 객체 지향의 기본 개념에 대해서 알아보려고 합니다.

위키피디아의 객체 지향의 특징에는 크게 8가지가 존재합니다.

  1. 비 객체지향 언어의 개념을 포함
  2. 객체와 클래스
  3. 클래스 기반 vs 프로토타입 기반
  4. 동적 Dispatch, Message Passing
  5. 캡슐화
  6. 상속, 델리게이션
  7. 다형성
  8. 재귀

지난 글에서 1~4까지를 정리했으니 이번 글에서는 5~8을 정리해보도록 하겠습니다. 글에서 사용되는 예제의 언어는 Swift를 사용합니다.

캡슐화 (Encapsulation)

캡슐화는 객체 지향 프로그래밍에서 객체의 프로퍼티와 메서드를 묶고 구현의 일부를 외부에 감추는 개념입니다. Swift에는 외부의 접근을 제어하기 위한 접근 제한자로 Open, Public, internal, fileprivate, private가 존재합니다. 자세한 내용은 여기를 참고해 주시고 이번 글에서는 간단한 예제를 통해 살펴보도록 하겠습니다.

 

일단 Swift에서 아무런 접근 제한자를 주지 않더라도 접근 수준이 internal로 설정됩니다. 따라서 굳이 접근 제한자를 몰랐더라도 지금까지 Swift를 문제없이 잘 사용할 수 있었던 것입니다.

 

그럼 Swift의 접근 제한자를 직접 사용해 보겠습니다~

위와 같이 ClassEncapsulation이라는 클래스를 만들고 가능한 모든 접근 제한자로 프로퍼티들을 각각 만들었습니다.

open, public

open과 public은 누구나 접근가능한 수준을 말합니다. 근데 두 개의 차이는 무엇일까요?

open, public의 차이점은 open은 class에만 쓸 수 있다는 점입니다.

위와 같이 Struct, Enum에 open 접근 제한자를 사용하려고 하면 오류를 발생시킵니다.

open, public을 사용하면 다른 어떤 곳에서도 해당 객체의 프로퍼티에 접근이 가능합니다.

접근이 가능하다는 말은 위와 같이 인스턴스를 만들고 해당 인스턴스의 프로퍼티에 접근할 수 있다는 것을 말합니다.

internal

internal은 해당 모듈의 모든 소스파일에서는 접근할 수 있는데, 다른 모듈에서는 접근이 불가능합니다. 앱, 프레임 워크의 내부 구조를 정의할 때 internal을 많이 사용한다고 합니다.

fileprivate

fileprivate의 이름을 보면 어떻게 접근을 제한할지 알 수 있는데요, 말 그대로 동일한 소스 파일에서만 접근이 가능하다는 말입니다. 즉 쉽게 말하면 해당 클래스가 정의된 소스 코드에서는 fileprivate로 선언된 프로퍼티에 접근할 수 있다는 말이 됩니다.

위와 같이 같은 소스 파일에서는 접근이 되지만 다른 소스파일에서 인스턴스를 생성하면 fileprivate 프로퍼티에는 접근할 수 없습니다.

private

private은 가장 접근이 제한된 수준을 말합니다. private로 선언한 변수를 포함하는 클래스나 해당 클래스의 익스텐션에서만 접근이 가능합니다.

객체 지향 프로그래밍을 지원하는 언어에서는 위와 같이 접근 제한자를 사용하여 객체의 프로퍼티에 대한 접근을 제어할 수 있습니다.

상속 (Inheritance)

상속은 어떤 클래스의 프로퍼티나 메서드를 그대로 사용할 수 있는 것을 말합니다.

예를 한 번 보겠습니다.

class Animal {
    func speak() {
        print("울음소리")
    }
}

class Cat: Animal {
    
}
let cat = Cat()
// Cat 클래스에는 speak라는 메서드가 없지만 상속받은 Animal에는 speak가 존재하므로 사용가능!
cat.speak()

위와 같이 Cat 클래스에는 speak()라는 메서드가 없지만 Animal 클래스를 상속받은 Cat 클래스의 인스턴스인 cat은 speak() 메서드를 사용할 수 있습니다. 이렇게 클래스 간에 종속 관계를 만들 수 있으며 메서드나 프로퍼티를 재사용할 수 있습니다.

다형성 (Polymorhpism)

방금 알아본 상속에서도 사용되는 다형성은 하나의 개념에 여러개의 개념을 넣을 수 있다는 뜻으로 객체 지향 프로그래밍에서는 오버라이딩, 오버로딩 메서드가 같은 이름으로 존재할 수 있는 것을 말합니다.

  • 오버라이딩
    • 같은 이름의 메서드가 여러 개의 클래스에서 다른 기능을 수행하는 것
  • 오버로딩
    • 같은 이름의 메서드가 갖는 인자가 다르면 다른 기능을 수행하는 것

간단하게 오버라이딩을 구현해보면 아래와 같습니다.

class Animal {
    func speak() {
        print("울음소리")
    }
}

class Cat: Animal {
    override func speak() {
        print("야옹")
    }
}
let cat = Cat()
cat.speak() // "야옹" 출력

위와 같이 Animal 클래스와 Cat 클래스에 모두 speak() 메서드가 있지만 서로 다른 기능을 수행하는 것을 볼 수 있습니다. 이렇게 같은 이름의 메서드가 존재할 땐 지난 글에서 알아봤듯 Dynamic Dispatch를 사용하여 런타임에서 메서드를 구분합니다.

 

오버로딩의 예도 한 번 볼까요?

Playground라는 클래스를 만들었고 play라는 이름의 메서드를 3개 만들었습니다. 하지만 각각 인자들은 다른 자료형과 다른 종류로 구성된 것을 볼 수 있습니다.

델리게이션 (Delegation)

Swift에는 델리게이션이 자주 쓰이는데요, 델리게이션은 해석하면 위임자라는 뜻으로 객체 지향 프로그래밍에서는 다른 객체의 컨텍스트에서 어떤 객체에 어떤 정보를 전달할 수 있는 것을 말합니다.

 

간단하게 Swift로 사용해보겠습니다.

// Delegation
protocol CallToHomeDelegation: class {
    func callToHome(from: String)
}

class PhoneUser {
    weak var delegation: CallToHomeDelegation?
    var name: String = "Pingu"
    func call(to: String) {
        print("\(to)에게 전화를 겁니다")
        delegation?.callToHome(from: self.name)
    }
}

class Home: CallToHomeDelegation {
    let phoneUser = PhoneUser()
    
    init() {
        phoneUser.delegation = self
    }
    func callToHome(from: String) {
        print("\(from)에게 전화가 왔어요")
    }
}
let home = Home()
home.phoneUser.call(to: "Mom")

위의 코드를 보면 Home 객체에서 callToHome(from:) 메서드를 수행한 적이 없는데도 불구하고 실행된 것을 볼 수 있습니다. 이는 Home 객체의 PhoneUser 객체가 call()이라는 메서드를 수행할 때 델리게이션을 통해 Home 객체의 callToHome(from:) 메서드를 수행하라고 전달했기 때문입니다.

 

위의 코드는 누군가에게 전화를 걸면 전화가 누구에게 왔다고 알려주는 그러한 코드인 것이죠.

열린 재귀 (Open Recursion)

열린 재귀를 지원하는 언어에서는 this나 self라는 특수 변수, 키워드를 사용하여 동일한 객체의 다른 메서드를 호출할 수 있습니다. Swift에서는 self를 사용할 수 있어요.

class Playground {
    func play(with: Int) {
        print("\(with)로 놉니다.")
    }
    func play(with: String) {
        print("\(with)로 놉니다.")
    }
    func play(with: String, at: String) {
        print("\(at)에서 \(with)로 놉니다.")
    }
    func play() {
        self.play(with: "Swift", at: "Mac") // self 키워드로 동일한 객체의 다른 메서드에 접근!
    }
}

위와 같이 self를 사용하여 동일한 객체의 다른 메서드나 프로퍼티에 접근할 수 있습니다.

반응형

'Computer > Anything' 카테고리의 다른 글

[OOP] 객체 지향 프로그래밍 기본 개념 공부 - 1  (1) 2021.04.18
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
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
글 보관함