[iOS-Swift] 객체 지향 프로그래밍 OOP

TIL 15일 차 - Swift 문법 객체 지향 프로그래밍 OOP

객체 지향 프로그램이란?

: 프로그램을 여러 개의 객체로 나누어 설계하고 구현하는 것

 

객체: class의 인스턴스 (프로퍼티+메서드)

객체는 서로 메시지를 주고받으며(메서드를 호출하는 것) 상호작용을 함

즉, 클래스의 인스턴스를 사용해서 개발을 지향하는 프로그래밍 방식

 

그럼 이 객체 단위로 코드를 구성하고 관리하는 게 뭐가 좋냐?

코드의 재사용성과 유지보수성이 좋아짐

 

또한 클래스의 인스턴스일급 객체로 간주됨

- 변수나 프로퍼티에 할당 가능

- 함수나 메서드에 파라미터, 반환값으로 사용 가능

- 런타임에 생성 가능

 

 

이러한 객체지향 프로그래밍엔 4가지 특징이 있다

 

1. 추상화

- 추상화는 복잡한 시스템을 단순화하여, 공통적인 특성이나 기능을 추출하여 파악하는 것을 의미함

- 핵심기능을 노출하고, 불필요한 세부 사항은 숨기는 것을 의미함

- 추상화를 통해 복잡성을 줄이고, 중요한 부분에만 집중 가능함

 

추상화의 예제

1. 자동차를 운전한다고 가정
2. 운전자에게 중요한 것: 핸들, 페달의 사용 방법
3. 내부적으로는 엔진과 브레이크 시스템 등의 복잡한 부분이 있겠지만, 운전자는 이런 세부사항을 알 필요 X
4. 자동차의 엔진이 바뀌어도 운전 방식은 동일하므로, 내부 변화에 대한 신경을 쓰지 않아도 됨

class Car {
	func drive() {
    	// 내부적으로는 복잡한 동작을 하지만
        // Car 객체를 사용할때는 drive 함수만 호출해주면 됨
    }
}

 

(장점)

- 복잡성이 낮아짐: 복잡한 세부내용을 숨겨서 서비스를 단순하게 다룰 수 있음

- 유지보수를 하기 쉬워짐: 세부 내용을 변경하더라도 사용하는 방법은 바뀌지 않으므로 유지보수가 편해짐

- 모듈화 가능: 각 객체가 독립적인 기능을 갖고 동작하기 때문에, 서로 독립적으로 수정할 수 있음 이를 통해 모듈 단위로 분리하여 개발할 수 있다.

 

 

 

2. 캡슐화

- 객체의 속성(프로퍼티)과 행동(메서드)을 하나의 단위로 묶어서 관리하는 것

 

캡슐화의 핵심은 캡슐화, 은닉화로 나누어짐

 

- 캡슐화 (관련된 프로퍼티와 행동을 묶어 놓는 것)

- 은닉화 (객체 내부의 중요한 데이터를 외부에서 접근하지 못하도록 감추거나 허용범위를 설정하는 것)

은닉화는 접근 제어자를 통해 외부에서의 접근을 허용하거나 막을 수 있다

 

 

캡슐화의 예제

class BankAccount {
    // 은닉화 된 데이터 (외부에서 직접 접근이 불가함)
    private var balance: Double = 0.0
    
    public func deposit(amount: Double) {
        if amount > 0 {
            balance += amount
        }
    }
    
    public func withdraw(amount: Double) -> Bool {
        if amount > 0 && amount <= balance {
            balance -= amount
            return true
        }
        return false
    }
    
    public func getBalance() -> Double {
        return balance
    }
}

 

(장점)

- 데이터의 무결성을 보장함

= 외부에서 직접 변경하지 못하게 하고, 객체 내부에서만 변경하게 만들면 데이터의 무결성을 보장할 수 있음

 

- 데이터를 보호하고 보안성을 높일 수 있음

= 외부에서 직접 접근을 못하게 하면 데이터가 손상되거나 예상치 못하게 변경되는 것을 막을 수 있음

 

 

 

3. 상속

- 하위 클래스가 상위 클래스의 속성(프로퍼티)과 행동(메서드)을 물려받아 사용하는 것을 의미

- 하위 클래스에서는 상위 클래스에서 제공하는 연산 프로퍼티와 메서드를 재정의(override)하여 사용 가능

 

-상속받는 방법은 class를 선언할 때 클래스의 이름 뒤에 :를 붙인 뒤 상속받을 상위 클래스의 이름을 작성하면 됨

- class만 상속이 가능함

=struct, enum은 상속이 불가함

= protocol 채택은 class, enum, structural 모두 가능함

= 상속은 한 개의 클래스에서만 받을 수 있음 (다중상속 불가)

-super. 키워드를 사용해 상위클래스의 메서드나 프로퍼티에 접근 가능함

 

상속의 예제

// 부모 클래스 정의
class Animal {
    var name: String
    
    init(name: String) {
        self.name = name
    }
    
    func speak() {
        print("Animal makes a sound")
    }
}

// 자식 클래스가 부모 클래스를 상속
class Dog: Animal {
    
    // 자식 클래스에서 추가된 메서드
    func fetch() {
        print("\(name) is fetching!")
    }
    
    // 부모 클래스의 메서드를 재정의
    override func speak() {
        print("\(name) barks!")
    }
}

// 객체 생성 및 사용
let myDog = Dog(name: "모찌")
myDog.speak() // "모찌 barks!" (재정의된 메서드 호출)
myDog.fetch() //"모찌 is fetching!" (자식 클래스의 고유 메서드 호출)

 

(장점)

-코드의 재사용성이 높아짐

-기존 기능을 확장하거나 새로운 기능을 추가할 수 있음

(단점)

- 상속 계층이 깊어지면 클래스 간 의존성이 증가하고, 복잡성이 증가함

- 상위 클래스에 변화가 생기면 하위 클래스에도 영향을 미쳐 유지보수가 힘들어짐

 

 

4. 다형성

- 같은 이름의 메서드가 다양한 방식으로 동작할 수 있는 특성임

메소드 오버로딩(Overloading)과 메소드 오버라이딩(Overriding)을 통하여 다형성 구현 가능

 

 

(1) 메소드 오버로딩

- 같은 이름의 메서드를 파라미터의 타입이나 개수가 다르면 다른 메서드로 취급하는 방법

class Calculator {
    func add(a: Int, b: Int) -> Int {
        return a + b
    }
    
    func add(a: Double, b: Double) -> Double {
        return a + b
    }
}

let calc = Calculator()
print(calc.add(a: 1, b: 2)) // Int버전의 add 메소드 호출되어 결과는 3 출력
print(calc.add(a: 10.0, b: 3.4)) // Double버전의 add 메소드 호출되어 결과는 13.4 호출

 

 

(2) 메소드 오버라이딩

- 상속받은 부모 클래스의 메서드를 자식 클래스에서 재정의 하는 것

- func 키워드 앞에 override 키워드를 적어 재정의 가능함

- super 키워드를 사용하여 부모 클래스의 메서드 호출 가능

class Animal {
    func makeSound() {
        print("Animal makes a sound")
    }
}

class Dog: Animal {
    override func makeSound() { // 오버라이딩할때는 반드시 override를 func 앞에 붙임
        print("Dog barks")
    }
}

class Cat: Animal {
    override func makeSound() {
        super.makeSound() // 부모의 메서드도 호출
        print("Cat meow!") // 메서드 오버라이딩으로 재정의
    }
}

let dog = Dog()
let cat = Cat()
dog.makeSound() // Dog barks 출력
cat.makeSound() // Animal makes a sound Cat meow! 출력