[CS] OOP(객체 지향 프로그래밍)(feat. Swift)
일단 OOP를 왜 공부하게 됐는지부터 설명해 드리자면...
일단은 Moya를 공부하고 있었는데요... 하다 보니까 DIP에 대해서 공부하게 되는데 이제 DIP를 이해하는 데에 OOP에 대한 기본적인 개념부터 다시 정리하고 넘어가는 게 좋겠다는 생각이 들어서 여기까지 오게 되었습니다...
아무튼!
OOP는 프로그램 설계 방법론 중 하나입니다.
Object-Oriented Programming의 약어이며 명령형 프로그래밍에 속합니다.
한국어로 하면 객체지향 프로그래밍.
프로그램을 데이터, 처리방법 두 가지로 나누는 것이 아닌 객체(Object)라는 단위로 나누고 객체 간의 상호작용으로 설계하며
대표적으로 C++, 파이썬, Objective-C 가 지원합니다.
객체지향 프로그래밍에는 3가지 요소가 있습니다.
캡슐화, 상속, 다형성
이 세 가지를 알아봅시다.
1. 캡슐화(encapsulation)
프로그램 내에서 같은 기능을 목적으로 작성된 코드를 한 곳에 몰아서 작성합니다.
자바로 예시를 들면 한 개의 클래스에는 한 가지 목적(책임)을 갖도록 한다라고 이해할 수 있겠죠?
이렇게 되면 외부 클래스에서 다른 클래스를 함부로 염탐할 수 없게 막을 수 있습니다.
자바에서 쓰는 접근 제어자는 세 가지(private, protected, public)이며 필요에 따라
private으로 숨기거나
public으로 외부에 노출시켜 사용할 수 있도록 하고
protected는 상속받은 하위 클래스에게만 접근할 수 있게 해줍니다.
캡슐화에서 파생된 효과로는 정보은닉이 있습니다.
위에서 말한 private으로 숨기면 외부에선 접근하는 것이 안되고, 애초에 노출되지 않도록 아예 감춰버립니다.
2. 상속(inheritance)
위에서 잠깐 protected 얘기를 하면서 상속에 대한 얘기를 했는데 우리가 아는 그 상속이 맞습니다.
상속은 자식 클래스가 부모 클래스에게 특성, 기능을 물려받는 것입니다.
사용 예시를 들어보면
자동차의 공통적인 기능을 하는 부모 클래스 A가 있다. 전진, 후진 메서드와 속도 변수가 있다고 해봐요.
승용차 클래스와 트럭 클래스, 특수차량 등의 클래스들이 A클래스를 상속받으면 부모 클래스의 기능들을 그대로 쓸 수 있게 됩니다.
3. 다형성(polymorphism)
다형성이란 한자로 多形性이라 하는데 이는 말 그대로 다양한 형태를 가지는 성질이에요.
이를 적용해서 의미해석을 하자면 어떤 객체의 속성(property: 변수)이나 기능(method: 메서드)이 상황에 따라 여러 형태를 가질 수 있는 성질을 의미합니다.
다형성은 깊게 파고들면 좀 많이 어렵긴 한데
일단은 대표적인 예시 두 가지(overriding(오버라이딩), overloading(오버로딩))만 짚고 넘어가 보겠습니다.
Overloading(오버로딩)
오버로딩은 메서드의 시그니처(형태)를 다르게 써야 할 때 이를 재정의 해서 쓰는 것을 말합니다.
메서드명 자체는 동일하게 가져가고 매개변수의 유형, 개수가 달라지는 경우에 해당됩니다.
이때 리턴타입이나 값이 달라지는 건 오버로딩에 해당되지 않습니다.(이건 제네릭글을 쓰게 된다면 다뤄보겠습니다.)
예를 들면
func plus(first: Int, second: Int) -> Int {
return first + second
}
func plus(first: Int, second: Int, third: Int) -> Int {
return first + second + third
}
func plus(first: Int, second: Int) -> Double {
return Double(first + second)
}
위의 예시 중 처음 나오는 두 개의 메서드는 오버로딩의 매우 적절한 예시죠?
plus 메서드가 원형으로 존재하고 이를 오버로딩해서 파라미터를 세 개를 받는 메서드를 만들어 줬습니다.
하지만 세 번째 메서드를 보시면 리턴값만 바뀌어있죠?
위 사진에서 실제로 사용할 때 보면 파라미터가 3개짜리인 메서드는 아무런 에러가 없지만
두 개짜리 메서드는 모호한 사용이라고 뜹니다.
왜냐하면 실제로 사용할 때 우리가 리턴값을 미리 써놓고 쓰진 않으니까 그렇겠죠?
하지만 아래처럼 쓴다면 말이 달라지집니다.
let resultNumber: Double = plus(first: 1, second: 2)
왜냐하면 모호하지 않게 Double인 값을 받겠다!라고 선언해 줬기 때문에 에러가 안 생기는 겁니다.
Overriding(오버라이딩)
부모(혹은 상위) 클래스의 메서드를 자식(혹은 하위) 클래스에서 재정의해서 사용하는 방법입니다.
스위프트에서 보면 viewDidLoad 같은 생명주기 메서드들이 이에 속하죠.
class MainViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
}
위의 예시를 보시면 많이 익숙한 느낌이 드실 거예요.
앞에 override
키워드를 붙여주고 재정의 해서 쓰면 됩니다.
안의 super.viewDidLoad()
같이 super 메서드를 호출해 주는 이유는
super의 viewDidLoad에 내용을 추가해서 실행하기 위한 거라 꼭 있어야 되는 건 아니고 필요에 따라 제거해도 상관없습니다.
끝!