애플사이다의 iOS 개발 일지

[Swift] OOP에서 인스턴스란? 타입과 인스턴스, 객체와 인스턴스 본문

Swift/Swift 문법

[Swift] OOP에서 인스턴스란? 타입과 인스턴스, 객체와 인스턴스

Applecider 2021. 10. 24. 15:30

안녕하세요. 애플사이다 입니다.

Swift는 명령형, 객체지향 프로그래밍 패러다임을 기반으로 함수형 프로그래밍 패러다임 및 프로토콜 지향 프로그래밍 패러다임을 지향하는 언어입니다.

 

OOP (Object-oriented Programming, 객체지향 프로그래밍)에서 타입과 인스턴스란 무엇인지,

Swift에서는 왜 객체라는 용어 대신 인스턴스라는 용어를 사용하는지 정리해보겠습니다.

 


OOP란?

OOP (Object-oriented Programming, 객체지향 프로그래밍)는 컴퓨터 프로그램을 명령어의 목록으로 보는 시각에서 벗어나 여러 개의 독립된 단위, 즉 "객체"들의 모임으로 파악하여, 객체 간의 상호작용으로 프로그램의 동작을 구현하는 것이다.

기존의 계산기처럼 컴퓨터에 명령만 시키겠다는 관점에서 벗어나서, 세상의 모든 것을 객체로 표현하여 문제해결을 하겠다는 관점을 택한 것이다.

객체를 통해 특성 (프로퍼티)와 행위 (메서드)를 표현할 수 있다.

Swift에서 객체란?

하지만 Swift에서는 "객체 (Object)"라는 용어 대신 "인스턴스 (Instance)"를 사용한다.

Swift Language Guide의 Structures and Classes 챕터에서 확인할 수 있다.

An instance of a class is traditionally known as an object. However, Swift structures and classes are much closer in functionality than in other languages, and much of this chapter describes functionality that applies to instances of either a class or a structure type. Because of this, the more general term instance is used.

 

"인스턴스"라는 용어를 사용하는 이유는 Swift의 구조체가 독특하기 때문이다.

 

다른 언어에서 사용하는 "객체"는 클래스의 인스턴스를 의미한다. 다른 언어는 보통 구조체가 프로퍼티만 가지고 메서드를 가질 수 없다. 또한 클래스는 프로퍼티와 메서드를 가질 수 있다. 따라서 클래스가 매우 유용하고, 이 클래스의 인스턴스에 한정지어 객체라는 용어를 사용한다.

 

하지만 Swift는 구조체도 메서드를 가질 수 있다. 따라서 Swift의 구조체와 클래스는 매우 유사하다. 다른 언어와 달리 구조체를 매우 유용하게 사용할 수 있다. Apple도 공식문서인 Choosing Between Structures and Classes를 통해 기본적으로 구조체를 사용할 것을 권하고 있다. 클래스는 상속 때문에 구조나 메모리 사용 측면에서 복잡해질 수 있기 때문이다. (클래스의 상속 기능도 구조체에서 프로토콜 상속을 활용하여 대체할 수 있다.)

 

따라서 구조체와 클래스를 구분하는 객체라는 용어 대신, 구조체와 클래스 모두에 적용할 수 있는 인스턴스라는 용어를 사용하는 것이다.

타입과 인스턴스란?

Swift에는 구조체, 클래스, 열거형 같은 사용자 정의 타입이 있다. 이러한 타입을 사용하여 코드에 담고 싶은 대상의 특성과 동작을 표현한다.

특성은 프로퍼티로, 동작은 메서드로 정의한다.

 

타입은 설계도이다. 인스턴스는 설계도에 따라 만든 실체이다.

예를 들어 집의 구조를 설계하기 위해 House라는 클래스 타입을 정의할 수 있다. 그리고 설계도에 따라 집의 실체를 만들기 위해 인스턴스를 생성한다. 인스턴스를 초기화하면 메모리에 할당해서 실제로 동작하게 할 수 있다.

타입 설계 - 일반화, 추상화, 은닉화, 캡슐화

타입 설계는 일반화, 추상화, 은닉화, 캡슐화의 과정을 따른다.

  • 일반화 : 표현할 대상의 일반적인 특징과 기능을 찾는다. ex) 주소, 색깔, 층 수, 침실/화장실/부엌의 개수, 지붕 형태 등
  • 추상화 : 프로그램에서 다룰 특성을 추출한다. 나머지는 무시한다. ex) 색깔 (color), 침실의 개수 (bedroomCount) 등
  • 은닉화 : 접근 제어를 통해 중요한 정보가 외부에 드러나지 않게 감추는 것이다.
  • 캡슐화 : 중요한 정보와 동작 과정을 감춘 상태로, 외부에서 사용할 수 있는 창구를 만드는 것이다. ex) 인스턴스의 color 프로퍼티를 직접 변경하지 않고, 간접적으로 paintHouse 메서드를 사용한다.
enum Color {
    case blue, white, green, black
}

class House { // 타입은 "설계도"이다. 인스턴스의 특성 (프로퍼티)과 동작 (메서드)를 표현한다
    let name: String // 특성/동작을 "일반화" 및 "추상화"하여 코드로 나타낸다
    private var color: Color = .white // House 밖에서 마음대로 색깔을 바꿀 수 없도록 (값에 접근하거나 값을 변경할 수 없도록) "은닉화"한다
    var bedroomCount: Int = 3
    private var isLightOn: Bool = false // House 밖에서 마음대로 불을 켜고 끌 수 없도록 "은닉화"한다
    
    func paintHouse(in color: Color) {
        self.color = color
        print("색깔을 \(color)로 칠했습니다")
    }
    
    func turnLightsOn() { // 사용자가 알 필요가 없는 내부 동작과정은 메서드 내부에 "캡슐화"한다
        isLightOn = true
        print("불을 켭니다")
    }
    
    func turnLightsOff() {
        isLightOn = false
        print("불을 끕니다")
    }
    
    init(name: String, color: Color, bedroomCount: Int) {
        self.name = name
        self.color = color
        self.bedroomCount = bedroomCount
    }
    
    convenience init(name: String) {
        self.init(name: name, color: .white, bedroomCount: 3)
    }
}

// 인스턴스는 설계도에 따라 만든 실체이다
// 인스턴스를 초기화하면 메모리에 할당해서 실제로 동작하도록 한다. 이니셜라이저를 통해 인스턴스를 생성하는 동시에 초기화할 수 있다
var greenHouse: House = House(name: "greenHouse", color: .green, bedroomCount: 5) // House.init(...)의 축약 표현
var whiteHouse: House = House(name: "whiteHouse")

greenHouse.paintHouse(in: .black) // 색깔을 black로 칠했습니다
//greenHouse.color = .black       // 컴파일 에러 - private이므로 값 변경이 불가하다 ('color' is inaccessible due to 'private' protection level)
whiteHouse.turnLightsOn()         // 불을 켭니다

 

- Reference

 

🍎 포스트가 도움이 되었다면, 공감🤍 / 구독🍹 / 공유🔗 / 댓글✏️ 로 응원해주세요. 감사합니다.

 

Comments