# OOP 객체 지향 프로그래밍 - 아니 지난주에 swift는 pop가 짱이라고 안했어? - 프로그램에 쓰일 많은 `객체`를 만들어 놓고, 객체들끼리 상호 작용을 통해서 하나의 프로그램이 만들어지게 하는 방식이다. #### 객체지향 프로그래밍의 4가지 특성 - 1. 추상화(추상:여러 가지 사물이나 개념에서 공통되는 특성이나 속성 따위를 추출하여 파악하는 작용.) - 객체의 공통적인 속성과 기능을 추출하여 정의하는것 - 1-1. 자동차 객체 - 공통 특징: 자동차는 이동 수단 기능이다. - 여러 종류의 자동차(세단, SUV)에 공통적으로 적용되는 기본적인 기능(엑셀, 브레이크)을 정의합니다 이런건 어떤 자동차이든 공통적일것이다.(추상!) 이제 각각 구체적인 자동체 객체?에 모델?에 세부적인 구현을 더 할 수있다.(공통적인 부분에 있어 객체를 쓰면 oop? 프로토콜로만들면 pop?) - 추상화의 중요한 점 - 일반화: 추상화는 특정 사례의 구체적인 세부 사항을 배제하고, 일반적인 개념을 형성한다. 이를 통해 다양한 상황이나 객체에 적용할 수 있는 일반적인 규칙?인 인터페이스를 만들 수 있습니다. - 추상화는 복잡한 시스템을 이해하고 관리학기 쉬운 부분으로 나누는데 중요한 역활을 하는거 같습니다. 이러한 추상화만으로도 유지보수성, 확장성을 향상 시키는데 큰 도움이 될꺼 같습니다. - 2. 캡슐화 - 캡슐화는 객체의 내부 상태를 숨기고, 외부에서는 객체의 기능만을 사용할 수 있도록 인터페이스를 제공하는것입니다. 이를통해서 객체의 세부 내용을 외부로 부터 보호하고, 데이터를 안전하게 관리할 수 있습니다. - 캡슐화 특징 - 은닉화 객체의 내부 구현을 숨기고, 외부에서는 객체의 기능만을 사용할 수 있습니다. - 객체의 데이터를 직접적으로 접근하는 것을 제한함으로써, 데이터의 잘못된 접근을 방지합니다. ```swift class BankAccount { private var balance: Double = 0.0 func deposit(amount: Double) { balance += amount } func getBalance() -> Double { return balance } } ``` - 은행계좌에 캡슐화를 통해서 잔액(balance)을 안전하게 관리할 수 있도록 합니다. - 잔액은 전부 외부에서 접근할 수 없고, 입금이나 확인을 통해서 조작 가능합니다. `private`를 선언하여 클래스 외부에서 접근할 수 없습니다. 관련 메서드만 사용해야 한다. - 캡슐화는 복잡성을 줄일수 있기에, 유지보수에 좋고, 데이터 보호와 같은 중요한 정보에 좋다. - 3. 상속(Interitance) - 상속은 클래스에서만 가능하면서도 class의 장점이자 또한 단점으로 얘기될 수 있습니다.(자세한건 추후에 알아보시죠!) - 상속은 한 클래스(부모)의 특성?(프로퍼티, 메서드)을 다른 클래스(자식)가 받아서 사용할 수 있도록 하는 프로그래밍 기법입니다. - 상속을 통해 코드 재사용을 높이고, 중복일 줄일수있습니다. - 상속의 주요 특징 - 재사용성 -> 기존 클래스의 코드를 재사용하여 새로운 클래스를 만들 수 있습니다. - 확장성 -> 기존 클래스의 기능을 확장하거나 수정하여 새로운 기능을 추가할 수 있습니다. - 계층 구조 -> 클래스 간의 계층적 관계를 형성하여, 보다 구조화된 방식으로 코드를 관리할 수 있습니다. ```swift class Animal { var name: String init(name: String) { self.name = name } } class Dog: Animal { func bark() { print("Woof!") } } ``` - 동물 클래스 상속 진행 - 기본 클래스 Animal을 정의하고, 상속받은 Dog클래스 정의 - Animal' 클래스에는 모든 동물이 공통적으로 가질 수 있는 속성과 메서드가 정의됩니다. - Dog'와 클래스에서는 'Animal'의 특성을 이어받고, 추가적인 특성을 더합니다. - name 속성을 상속받아 사용가능함 - 여기서 오버라이드 재정의 하여 사용할 수 있습니다. - 4. 다형성(상속과 연관있는 개념, 한 객체가 다른 여러형태로 재구성되는것) - 다형성을 통해 하나의 메서드 호출이 다양한 객체 타입에 대해 다른 동작을 할 수 있습니다. 이는 코드의 유연성과 재사용성을 증가시킵니다. - 하나의 상위클래스에서 받은 하위클래스는 모두 똑같은게 아니다! - 오버로드와 오버라이딩을 하여 자식클래스가 다양한 형태로 존재 할 수 있게 하는것이 다형성이다. ```swift protocol Shape { func draw() } class A: Shape { func draw() { print("Drawing A") } } class B: Shape { func draw() { print("Drawing B") } } func drawShape(shape: Shape) { shape.draw() } let a = A() let b = B() drawShape(shape: a) drawShape(shape: b) ``` - Shape 프로토콜은 draw 메서드를 정의합니다. A과 B 클래스는 각각 Shape 프로토콜을 채택하고 draw 메서드를 자신의 방식으로 구현합니다. drawShape 함수는 Shape 타입의 인자를 받아 해당 타입의 draw 메서드를 호출합니다. 이를 통해 다형성이 구현되며, drawShape 함수는 A이나 B 객체를 전달받아 각각의 draw 메서드를 실행합니다.