LG CNS 부트캠프 학습일지 14일차
학습 내용
- 상속 (Inheritance)
- 다형성 (Polymorphism)
객체지향 프로그래밍
객체지향 프로그래밍이 무엇인지 설명하라고 하면 뭐라고 말할 수 있을까. 객체를 지향하는 프로그래밍이라고 설명한다면 이름을 그대로 읽은 것과 다르지 않다. 객체가 무엇인지 이해해야 할 것이다. 클린코드(Clean Code)에서는 객체와 자료구조를 대비되는 개념으로 설명한다. 자료구조는 자료를 있는 그대로 드러낸다. 하지만 할 수 있는 것을 정의하지 않는다. 반면 객체는 자신의 자료를 드러내지 않는다. 대신에 메소드를 제공하여 할 수 있는 것을 드러낸다.
객체지향 프로그래밍은 여러 특징을 가지고 있다.
- 상속 (Inheritance)
- 다형성 (Polymorphism)
- 캡슐화 (Encapsulation)
- 추상화 (Abstraction)
상속 (Inheritance)
자식 클래스가 부모 클래스를 상속받아서 부모 클래스의 필드와 메소드를 재활용한다. 반복하지 말라(DRY, Don’t Repeat Yourself)는 원칙을 실천하는 대표적인 방법 중 하나이다. 상속보다는 조합을 선호하라 (favor composition over inheritance) 라는 격언이 있을 정도로 혹자는 상속은 최대한 피해야한다고 말하기도 한다. 마인크래프트 모드를 만들면서 어쩔 수 없이 상속을 많이 사용했던 경험에 비추어볼 때 이렇게 말할 수 있다. 상속을 과도하게 사용하면 코드를 이해하기 더 어려워지지만 조합이라고 크게 다르지 않다. 결국 상속과 조합 중에서 어떤 것을 사용할지 선택할 때 코드를 더 쉽게 이해할 수 있는 것이 무엇인지 충분히 고민하는 것이 좋을 것이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class ParentClass {
public void doSomething() {
}
}
class ChildClass extends ParentClass {
public void doSomethingMore() {
super.doSomething();
this.doSomethingElse();
}
public void doSomethingElse() {
}
}
다형성 (Polymorphism)
다형성이란 무엇인가. 문자 그대로 이해하면 어떤 객체가 어려 형태를 띨 수 있다는 것이다. 구체적으로 말하면 자식 클래스의 인스턴스가 부모 클래스의 자료형을 띨 수 있다는 것이다. 다양한 자식 클래스의 인스턴스를 부모 클래스 자료형으로 다루면 동일한 메소드를 일괄적으로 호출할 수 있다. 이 방식으로 코드를 작성하면 자료형에 따라서 다른 메소드를 호출하기 위해 조건문을 나열하는 구현방식을 최대한 피할 수 있고 가독성을 높일 수 있다는 장점이 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class ParentClass {
public void doSomething() {
System.out.println("Hello Parent");
}
}
class ChildClass extends ParentClass{
@Override
public void doSomething() {
System.out.println("Hello Child");
}
}
class Main {
public static final void main(String[] args) {
List<ParentClass> objects = new ArrayList<>(
new ParentClass(),
new ChildClass()
);
for (ParentClass object : objects) {
object.doSomething();
}
}
}
오버로딩 (Overloading) vs 오버라이딩 (Overriding)
같은 이름의 메소드를 다룬다는 점에서 동일하다. 차이점은 그것이 하나의 클래스 안에서 벌어지는지 아니면 서로 다른 클래스에서 벌어지는가에 달려있다. 하나의 클래스는 이름이 같은 메소드를 여러 개 가질 수 있다. 하지만 시그니처(signature)는 달라야 한다. 시그니처란 메소드의 반환값과 매개변수의 자료형으로 정해지는데 예를 들어 아래와 같다.
1
2
3
4
5
6
7
8
9
class MyClass {
public void doSomething() {
System.out.println(10);
}
public void doSomething(int number) {
System.out.println(number);
}
}
자식 클래스가 부모 클래스의 메소드를 다시 정의하는 것을 오버라이딩이라고 한다. 예를 들면 아래와 같다.
1
2
3
4
5
6
7
8
9
10
11
12
class ParentClass {
public void doSomething() {
System.out.println("Hello Parent");
}
}
class ChildClass extends ParentClass{
@Override
public void doSomething() {
System.out.println("Hello Child");
}
}
결론
객체지향 프로그래밍과 대비되는 개념으로 절차지향 프로그래밍이 있다. C언어 등에서 일반적으로 작성한 코드가 대표적이 예다. 모든 공학적인 문제가 그렇듯이, 객체지향 프로그래밍이 절차지향 프로그래밍보다 모든 면에서 우월한 방법론인 것은 아니다. 객체지향 프로그래밍은 결국 코드를 조금 더 이해하기 쉽게 작성하기 위한 방법론이고, 개발자는 객체지향 프로그래밍의 장점과 단점을 이해하고 언제 사용하면 적합한지 판단할 줄 알아야 할 것이다. 사실 이렇게는 누구나 말할 수 있는 것이고 객체지향 프로그래밍을 언제 사용하면 좋은지 판단할 줄 알아야 고급 개발자가 될 수 있을 것이다. 그리고 이것은 경험에 의해서 직관적으로 이루어지지 않을까 감히 예상해본다.
조건문은 코드를 이해하기 어렵게 만드는 원인 중 하나이다. 어떤 코드를 이해하기 어렵다고 느껴지는 경우는 그 함수가 하나보다 더 많은 일을 할 때이다. 그리고 어떤 함수에 조건문이 있다는 것은 그 함수는 하나보다 더 많은 일을 하는 경우가 많다. 다형성(Polymorphism)을 사용하는 것은 코드를 이해하기 어렵게 만드는 조건문을 줄여보려는 노력이다.
Comments powered by Disqus.