Post

객체지향 프로그래밍

객체란 무엇인가?

객체는 여러 개로 정의되어 있다.

  • 소프트웨어 세계에 구현할 대상이며 속성과 기능을 가지는 프로그램 단위
  • 이름(name)과 값(value)으로 구성된 프로퍼티(property)의 정렬되지 않은 집합
  • 어떠한 속성값과 행동을 가지고 있는 데이터
  • 상태와 행동을 함께 지닌 실체
속성값과 기능을 가지는 데이터라고 정의할 수 있겠다.


객체지향의 사실과 오해

객체를 설명할 때 쉬운 이해를 위해 현실의 사물에 빗대어 설명하곤 한다.

이해하는 데에 도움은 되지만 완벽히 같은 개념은 아니다.

객체지향의 사실과 오해 에 따르면 객체는 협력적이고, 자율적이여야 한다.

객체는 다른 객체의 요청을 받아들일 수 있는 상태여야 하며, 요청을 응할지, 어떤 방식으로 응답할지는 객체 스스로 판단한다.

현실의 사물과 다른 가장 큰 이유다.

현실에서 음료수 캔을 객체 B라고 가정하자. 사람이라는 객체 A는 음료수 캔을 따려고 한다.

A가 B을 딸 때, B가 스스로 뚜껑을 딴 것인가?

아니다. 뚜껑이 A에 의해 열렸다.

그렇다면 디지털 세계에서는 어떨까?

A가 B를 따기 위해서는 B에게 요청을 보내야 한다.

요청을 받은 B는 스스로 뚜껑을 연다.

객체


객체지향과 절차지향

절차지향

절차지향

  • 문제를 여러 개의 함수로 나누어서 처리한다.
  • 프로시저와 데이터 간의 접근이 자유롭다.
  • 처리 속도와 실행 속도가 빠르다.
  • 캡슐화가 저하되어 유지보수가 어렵다.

ex. C언어


객체지향

객체지향

  • 문제를 여러 개의 객체로 나누어서 처리한다.
  • 코드 재사용이 용이하다.
  • 유지보수가 쉽다.
  • 처리 속도가 상대적으로 느리다.
  • 객체가 많으면 용량이 커진다.

ex. JAVA, Python, C#

객체지향


객체지향프로그래밍 특징

4가지 특징(캡슐화, 상속, 추상화, 다형성) 을 가지고 있다.

캡슐화

  • 관련된 필드와 메서드를 하나로 묶는다.
  • 실제 구현내용을 외부로부터 숨긴다.
  • 외부에서는 공개된 메서드를 통해 접근할 수 있다.
  • 외부에 영향 없이 객체 내부의 구현을 변경할 수 있다.
캡슐화는 기능을 외부에게 감추고, 기능을 사용하는 코드에 영향을 주지 않고 내부 기능을 변경할 수 있는 유연함을 가진다.


캡슐화를 위한 규칙

Tell, Don't Ask

  • 묻지 말고 시켜라
1
2
3
4
5
if(acc.getMemberShip() == REGULAR) {...}
// 묻고 있다. -> 외부에서 값을 직접 확인하고 있다.

if (acc.hasRegularPermission()){...}
// 시킨다. -> 외부에서 값을 확인시키고 있다.

Demeter's Law

  • 외부에 자료를 숨기는 대신(필드값을 공개하지 않는 대신) 함수를 공개
  • 외부에서 어떤 자료를 가지고 있는지 몰라야 한다.
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// 잘못된 예시
public class Address {

    private String region;
    private String details;

    public String getRegion(){
      return region;
    }
}

@Service
public class RegionService {

    public boolean checkSeoulRegion(final Address address) {
        if("서울".equals(address.getRegion())) {
            return true;
        }
    }
}

---
// 올바른 예시
public class Address {

    private String region;
    private String details;

    public boolean isSeoulRegion() {
        return "서울".equals(region);
    }
}

@Service
public class RegionService {

    public boolean checkSeoulRegion(final Address address) {
        if(address.isSeoulRegion()) {
            return true;
        }
    }
}


상속

  • 상위클래스의 모든 것을 하위 클래스가 이어받는다.
  • 이는 코드의 중복을 없애고 개발단계와 유지보수 단계에서의 비용을 줄여준다.

상속보단 조립

  • 현재는 상속보다는 조립의 형태로 권장되고 있다.
  • 상속의 문제점
    1. 상위 클래스 변경 어려움
      • 상위 클래스가 변경되면 하위 클래스가 비 정상적으로 동작할 가능성이 높다. 상속1
    2. 클래스 증가
      • 새로운 조합이 생길때마다 새로은 클래스가 생긴다.
      • 새로운 조합이 생길때 어느 클래스를 상속 받아야 할지 어렵다. 상속2
    3. 상속 오용
      • 상위 클래스의 메서드를 호출할 가능성이 있다.
      • 이는 실수하기 쉬운 구조가 된다.


조립

  • 여러 객체를 묶어서 더 복잡한 기능을 제공할 수 있다.
  • 필드로 다른 객체를 참조하는 방식으로 조립 또는 객체를 필요 시점에 생성한다. -> 진짜 하위 타입인 경우에만 상속을 사용해야 한다.
1
2
3
4
5
6
7
8
9
public class FlowController {
  private Encryptor encryptor = new Encryptor(); // 필드로 조립

  public void process(){
    ...
    byte[] encryptedDate = encryptor.encrypt(date);
    ...
  }
}

Spring 프레임워크의 IOC 컨테이너가 조립의 개념을 사용한다.


추상화

  • 객체에서 공통된 속성과 행위를 추출하는 기법이다.
  • 복잡한 것을 이해하기 쉽게 단순화시킨다.
  • 어떻게?
    1. 객체들 간의 공통점은 취하고 차이점은 버리는 일반화를 통해 단순하게 만든다.
    2. 중요한 부분을 강조하기 위해 불필요한 세부 사항을 제거함으로써 단순하게 만든다.

타입 추상화

  • 여러 구현 클래스를 대표하는 상위 타입을 도출한다.
  • 흔히 인터페이스 타입으로 추상화한다. 타입 추상화


다형성

  • 한 객체가 여러 타입을 갖는 것이다.
  • 같은 이름의 메서드를 호출하더라도 객체에 따라 다르게 동작하는 것을 말한다.
  • 오버로딩과 오버라이딩도 다형성의 사례라고 볼 수 있다. 다형성

오버 로딩(overloading)

  • 사전적으로는 과적하다 라는 뜻이다.
  • 동일한 메서드 이름의 존재를 허용하는 JAVA에서 사용된다.
자바의 한 클래스 내에 이미 사용하려는 이름과 같은 이름을 가진 메소드가 있더라도 매개변수의 개수 또는 타입이 다르면, 같은 이름을 사용해서 메소드를 정의할 수 있다
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class OverloadingMethods {
	public void print() {
		System.out.println("오버로딩1");
	}

	String print(Integer a) {
		System.out.println("오버로딩2");
		return a.toString();
	}

	void print(String a) {
		System.out.println("오버로딩3");
		System.out.println(a);
	}

	String print(Integer a, Integer b) {
		System.out.println("오버로딩4");
		return a.toString() + b.toString();
	}

}


오버 라이딩(overriding)

  • 부모 클래스로부터 상속받은 메소드를 자식 클래스에서 재정의한다.
부모 클래스의 메소드를 재정의하는 것이므로, 자식 클래스에서는 오버라이딩하고자 하는 메소드의 이름, 매개변수, 리턴 값이 모두 같아야 한다
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Person {
	void greet() {
		System.out.println("안녕하세요.");
	}
}

class Child extends Person {
	@Override
	protected void greet() {
		System.out.println("안녕");
	}
}

class American extends Person {
	@Override
	public void greet() {
		System.out.println("hello");
	}
}


누군가가 물어본다면

객체란 데이터(속성)와 그 데이터를 처리하는 함수(메서드)를 함께 묶어 놓은 것입니다.
객체는 클래스라는 틀에서 생성되며, 이 클래스는 객체의 구조와 행동을 정의합니다.
또한 객체 지향 프로그래밍(OOP)의 기본 단위로, 객체 지향 프로그래밍은 캡슐화, 상속, 추상화, 다형성 의 4가지 특성을 가집니다.
This post is licensed under CC BY 4.0 by the author.