
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! 출력'iOS > Swift ' 카테고리의 다른 글
| [iOS-Swift] 에러처리 (0) | 2026.01.14 |
|---|---|
| [iOS] ARC 순환참조 해제 문제 (0) | 2026.01.14 |
| [iOS-Swift] 스위프트에서 사용자 입력받기 (0) | 2026.01.13 |
| [iOS-Swift] 문법 기초주차 과제 최종 리펙토링 (0) | 2026.01.12 |
| [iOS-Swift] ARC (1) | 2026.01.12 |