Skip to content

Instantly share code, notes, and snippets.

@sungjaeHong
Created October 11, 2016 10:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sungjaeHong/db5a2f6784eca3ab97d2fa36b967a402 to your computer and use it in GitHub Desktop.
Save sungjaeHong/db5a2f6784eca3ab97d2fa36b967a402 to your computer and use it in GitHub Desktop.
객체지향프로그래밍(OOP)의 특징.md

#객체지향(OOP)의 특징

##추상화

  • 공통의 속성이나 기능을 묶어 이름을 붙이는 것
  • 추상화가 가능한 개채들은 개체가 소유한 특성의 이름으로 하나의 집합(class)를 이룬다.
  • 객체지향적 관점에서 클래스를 정의하는 것도 추상화라고 정의가 가능하다.
  • 예를들어 사과, 배, 포도라는 객체가 있을 때 이것들을 과일으로 묶으며 추상화가 가능하다.

#캡슐화

  • 낮은 결합도를 유지할 수 있도록 해주는 객체지향 설계원리.
  • 정보은닉을 이용하여 결합도를 유연하게 한다.
public class ArrayStack{
	public int top;
	public int[] itemArray;
	public int stackSize;
	
	public ArrayStack(int stackSize){
		itemArray = new int[stackSize];
		top = -1;
		this.stackSize = stackSize;
	}
	
	public boolean isEmpty(){
		return	(top == -1);
	}
	public boolean isFull(){
		return (top == this.stackSize -1);
	}
	
	public void push(int item){
		if(isFull()){
			System.out.println("Insert Failed. Becouse Stack is Full!");
		} else{
			itemArray[++top] = item;
			System.out.println("Insert item : " + item);
		}
	}
	
	public int pop(){
		if(isEmpty){
			System.out.println("Delete Failed. Becouse Stack is Empty!");
			return -1;
		} else{
			return itemArray[top--];
		}
	}
	
	public int peek(){
		if(isEmpty()){
			System.out.println("Peeking Failed. Becouse Stack is Emplty!");
			return -1;
		} else{
			return itemArray[top];
		}
	}
}

public class StackClient{
	public void static main(String[] args){
		ArrayStack stack = new ArrayStack(10);
		stack.itemArray[++stack.top] = 20;
		System.out.println(stack.itemArray[stack.top]);
	}
}

/*
	만약 캡슐화를 하지않는다면(모두 public으로 구현한다면)
	ArrayStack에 구현한 push나 pop등을 쓰지 않고 StackClient에서 바로 배열에 접근이 가능하다.
	이런 경우 두 클래스는 강한 결합이 발생한다.
	예를들어 ArrayStack을 ArrayList로 변경하여 구현하면 StackClient 또한 변경해야한다.
*/

public class StackClient{	//ArrayStack클래스가 Array을 ArrayList로 변경되었을때
							//StackClient또한 변경되어야한다.(만약 ArrayStack을 100군데에서 사용하면 100 다바꿔야함....)
	public void static main(String[] args){
		ArrayStack stack = new ArrayStack(10);
		stack.itemArrayList.add(20);
		System.out.println(stack.itemArrayList.size()-1);
	}
}

만약 캡슐화를 하여 정보은닉 + 결합도를 낮춘다면 ArrayStack 내부가 변하던 말던 사용방법은 동일할 것이다. 따라서 소스를 변경하는 일은 발생하지 않음.

public class ArrayStack{
	private int top;				//정보은닉을 통해 외부에서 접근 불가능하도록 수정
	private int[] itemArray;		//정보은닉을 통해 외부에서 접근 불가능하도록 수정
	private int stackSize;			//정보은닉을 통해 외부에서 접근 불가능하도록 수정
	
	public ArrayStack(int stackSize){
		itemArray = new int[stackSize];
		top = -1;
		this.stackSize = stackSize;
	}
	
	public boolean isEmpty(){
		return	(top == -1);
	}
	public boolean isFull(){
		return (top == this.stackSize -1);
	}
	
	public void push(int item){
		if(isFull()){
			System.out.println("Insert Failed. Becouse Stack is Full!");
		} else{
			itemArray[++top] = item;
			System.out.println("Insert item : " + item);
		}
	}
	
	public int pop(){
		if(isEmpty){
			System.out.println("Delete Failed. Becouse Stack is Empty!");
			return -1;
		} else{
			return itemArray[top--];
		}
	}
	
	public int peek(){
		if(isEmpty()){
			System.out.println("Peeking Failed. Becouse Stack is Emplty!");
			return -1;
		} else{
			return itemArray[top];
		}
	}
}
public class StackClient{
	public void static main(String[] args){
		ArrayStack stack = new ArrayStack(10);
		stack.push(20);
		System.out.println(stack.peek());
	}
}
/*
	이로써 ArrayStack의 내부가 어떻게 변하던, 상관없이 동일한 메소드를 통해 사용이 가능해진다.
*/

#상속성(일반화 관계)

  • 상속은 부모가 가지고 있는 재산(코드)를 자식에게 물려주는 것을 말한다.
  • 상속을 받게 되면 하위 객체에서 상위 객체의 필드와 메소드를 사용 할 수 있다.
  • 상속은 이미 잘 개발된 객체를 재사용해서 새로운 객체를 만들기 때문에 코드의 중복을 줄여준다.
상위객체 : value1필드와 getValue1()의 메소드로 구성  
하위객체 : value2필드와 getValue2()의 메소드로 구성  
만약 이와 같다면 하위객체에서 getValue1()이 호출이 가능하다.(부모의 메소드를 호출함)
  • 따라서 동일한 기능을 또 구현할 필요 없이 코드를 재사용 할 수 있는 장점이 있음.
  • 단 무분별한 상속은 빚(쓰지않는 코드)이 될 수 있다.
  • 이를 방지하기위해 피터 코드의 상속 규칙이 있다.
  1. 자식클래스와 부모클래스 사이는 '역할수행(is role played by'가 아니어야한다. - 첫번째 규칙인 자식클래스가 부모 클래스의 역할 중 하나를 표현하는지 점검한다. - 운전자는 어떤 순간에 사람이 수행하는 역할의 하나다. - 마찬가지로 회사원 또한 사람이 어떤 순간에 수행하는 역할의 하나다. - 따라서 사람-운전자 또는 사람-회사원이 상속관계로 표현되어서는 안된다.
  2. 한 클래스의 인스턴스는 다른 서브 클래스의 객체로 변환할 필요가 절대 없어야한다. - 두번째 규칙인 자식 클래스의 인스턴스들 사이에 변환관계가 필요한지 점검한다. - 운전자는 어떤 시점에 회사원이 될 필요가 있으며 회사원또한 운전자가 될 필요가 있다. - 회사로 출퇴근하는 동안에는 운전자로서의 역할을 수행하며, 출근 후에는 회사원으로 역할을 수행한다. - 이런 경우 객체의 변환작업이 필요하므로 규칙에 위배된다.
  3. 자식 클래스가 부모 클래스의 책임을 무시하거나 재정의하지 않고 확장만 수행해야한다. - UML만 보아서는 사람, 운전자, 회사원 클래스에 어떤 속성과 연산의 정의되어있는지 알수가 없기 때문에 점검이 불가능하다.
  4. 자식 클래스가 단지 일부 기능을 재사용할 목적으로 유틸리티 역할을 수행하는 클래스를 상속하지 않아야한다. - 기능만 재사용할 목적으로 상속 관계를 표현하지는 않았으므로 규칙을 준수한다.
  5. 자식클래스가 역할(role), 트랜잭션(transaction), 디바이스(device) 등을 특수화해야한다. - 슈퍼클래스가 역할, 트랜잭션, 디바이스를 표현하지않았으므로 규칙에 위배된다.

#다형성

  • 서로 다른 클래스의 객체가 같은 메시지를 받았을 때 각자의 방식으로 동작하는 능력.
abstract class Pet {
	public abstract void talk();
}
class Dog extends Pet {
	public void talk(){...}
}
class Cat extends Pet {
	public void talk(){...}
}
class Parrot extends Pet {
	public void talk(){...}
}

class Main{
	public static void gourpTalk(Pet[] p) {
		int i;
		for(i=0;i<p.size();i++){
			p[i].talk();
		}
	}
	
	public static void main(String[] args) {
		Pet[] p = {new Dog(), new Cat(), new Parrot()};
		groupTalk(p);	//Dog, Cat, Parront에 정의된 talk가 각각 실행된다.
	}
}
  • 메소드 오버로딩
class Overloading {
	public void print(String param) {
		System.out.println(param + ": 문자열");
	}
	public void print(int param) {
		System.out.println(param + ": 숫자");
	}
}
class Main {
	public static void main(String[] args) {
		Overloading overLoading = new Overloading();
		overLoading.print("123");	//"123: 문자열"
		overLoading.print(123);		//"123: 숫자"
	}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment