본문 바로가기
프로그래밍/OOP

객체지향 프로그래밍의 특징

by Daniel.kwak 2018. 10. 19.

목표

객체지향의 4가지 특징을 이해한다.


1.Abstraction(추상화)


공통된 속성이나 행위를 추출하는 작업. 사물들의 공통된 특징, 즉 추상적 특징을 파악해 인식의 대상으로 삼는 행위이다. 구체적인 사물들의 공통적인 특징을 파악해서 하나의 개념으로 다루게 된다. 각 개체의 구체적인 개념이 아닌 추상적인 개념에 접근해야 향후 유연한 설계가 가능하다.

ex) 아우디, BMW, 벤츠는 모두 자동차라를 공통적인 특징을 지닌다.


2.Encapsulation(캡슐화)

캡슐화는 낮은 결합도를 유지할 수 있도록 설계하는 객체지향의 특징이다.

*응집도(Cohesion):모듈 안의 요소들이 얼마나 밀집하게 묶여있는지, 관련이 있는지를 말한다.

*결합도(Coupling):모듈이 다른 모듈애 얼마나 의존적인지를 나타낸다. 


또한 캡슐화는 정보은닉을 통해 높은 응집도와 낮은 결합도를 갖도록 한다.

*정보은닉(Information Hiding): 외부에 노출되지 않는, 접근할 수 없도록 제한을 두는 것. private 키워드. 은닉화가 필요한 이유는 SW는 결합이 많을수록 문제가 다양해지고 유지보수가 어려워지게 때문이다.


ex) 스택을 사용한 자료구조를 만들어보자.



public class ArrayStack {
	/* 자료구조는 상황에 따라 변경될 가능성이 늘 존재한다. 
	외부에서 접근할 수 없도록 private키워드로 은닉화 한다.  */
	private int top; 
	private int[] stack;
	private int size;
}

public class StackClient{
	public static void main(String[] args) {
		ArrayStack arrayStack = new ArrayStack();
		arrayStack.push(20);
		System.out.println(arrayStack.peek());
	}
}


스택을 호출한 메인함수에서는 이 스택의 push,peek 연산이 어떻게 구현되는지는 알 수가 없다. 

만약 스택안의 자료구조를 배열이 아닌 링크드리스트나, 기타 다른 자료구조로 변경하고 싶더라도 스택 클래스만 변경하면 되기 때문이다.



3.Generaliztion(일반화 관계, 상속)

일반화 관계는 객체지향 프로그래밍 관점에서 상속관계라고도 한다. 따라서 속성이나 기능의 재사용성만 강조하는 경향이 있는데 일반화 관계의 일부일 뿐이다. 또한 일반화 관계는 또 다른 캡슐화이기도 하다.



사람입장에서는 구체적인 자동차가 은닉화 되어 있다. 즉, 어떠한 자동차든 상관이 없는 것이다. 일반화 관계는 한 클래스 안에 있는 속성 및 연산들의 캡슐화 뿐 아니라 자식클래스 자체도 캡슐화 하는 것이다. 


일반화 관계의 위임

만약 두 클래스 관계가 'is kind of' 관계가 아닐때 상속관계를 설정하면, 불필요한 속성까지도 물려받게 된다.

일반화 관계는 꼭 상속만을 위한것이 아니다.


public class MyStack extends ArrayList {
	public void push(String element) {
		add(element);
	}
	public string pop(){
		return remove(size()-1);
	}
}

상속을 받았으므로 ArrayList의 메소드를 그대로 가져다 쓸 수 있다. 그러나 사실 Stack 자료구조와는 딱히 관련이 없는것들이다. 자칫 Stack의 기본 무결성 조건인 LIFO을 벗어날 위험이 있기 때문이다. (다시 말해 스택과 ArrayList는 is a kind of관계가 아니다.)


어떤 모듈의 일부 기능만 사용하고 싶을 경우, 이럴 때 위임(delegation)을 사용한다.

위임이란, 자신이 직접 기능을 실행하지 않고, 다른 모듈의 객체가 기능을 실행하도록 위임하는 것이다. 따라서 일반화 관계는 클래스 관계지만 위임은 객체 사이의 관계이다. 


이제 '위임'을 사용해 일반화 관계를 대신해보자.

1.기존 자식클래스에서 부모클래스를 참조하는 속성을 만든다.(자바에서는 이 속성 필드를 this로 초기화 한다.)

2.기존 자식클래스에서 부모클래스 메소드를 제거하고, 위임된 this필드를 사용하여 재구현한다.



//일반화 관계 제거 
public class MyStack {
	//슈퍼 클래스 객체를 생성 후 대입 
	private ArrayList arrayList = new ArrayList();
	public void push(String element) { arrayList.add(element);}
	public string pop() {return arrayList.remove(size()-1);}
	//사용된 메서드 추가 및 위임 속성 필드를 참조하도록 변경
	public boolean isEmpty() { return arrayList.isEmpty();}
	public int size() { return arrayList.size();}

}


4.다형성

다형성이란 서로 다른 클래스의 객체가 같은 메세지를 받았을때 각자의 방식으로 동작하는것을 말한다.

다형성을 사용하는 코드와 사용하지 않는 코드를 살펴보자. 


public class Cat{
	public void meow() { System.out.println("야옹");}
}
public class Dog{
	public void bark() { System.out.println("멍멍");}
}
public class Parrot{
	public void sing() { System.out.println("안뇽");}
}

public class static Main{
	public static void main(String [] args){
		Cat cat = new Cat();
		Dog dog = new Dog();
		Parrot parrot = new Parrot();
		cat.meow();
		dog.bark();
		parrot.sing();
	}
}


//부모 추상 클래스
public abstract class Pet {
	public abstract void talk();
}

//자식 클래스
public class Cat extends Pet{
	public void talk {System.out.println("야옹");}
}

public class Dog extends Pet {
	public void talk {System.out.println("멍멍");}
}

public class Parrot extends Pet{
	public void talk {System.out.println("아룡");}
}

public class Main{
	public static voic main(String [] args){
		Pet [] pets = {new Cat() , new Dog(), new Parrot() };
		for(int i = 0; i < pets.length ; i ++) {
			pets.talk();
		}
	}
}