728x90

 [ 클래스의 관계 ]

 1. Has-A 관계(포함 관계)
   => A has a B = A 가 B 를 가지고 있다 = B가 A에 포함되어 있다.
   => 일반적인 클래스의 관계이며, 특정 클래스 내에
        다른 클래스를 포함시켜 사용하는 관계
    ex) class A {
     B b = new B();
    }
2. Is-A 관계(상속 관계)
    => A is a B = A 는 B 이다 = A 는 B 를 상속받은 관계이다. (자신 포함)
    => 초등학생은 학생이다 = 초등학생 is a 학생(O)
       컴퓨터는 기계장치이다 = 컴퓨터 is a 머신(O)
       학생은 학생이다 = 학생 is a 학생(O)
    => 스파이더맨은 사람이다(O)
       사람은 스파이더맨이다(X)
    ex) class A extends B {}
  

 [ instanceof 연산자 ]

 - 좌변의 객체(참조변수)가 우변의 클래스 타입(상속관계)인지 판별하는 연산자
 - 주로 if문에 결합하여 판별하는데 사용되며
  판별 결과가 true 이면 형변환이 가능한 관계(업캐스팅 또는 다운캐스팅)
판별 결과가   false 이면 절대로 형변환 불가능
  
 < 기본 문법 >
 if(A instanceof B) {}
 => A는 참조변수(인스턴스), B는 클래스명

 

public class Ex {

	public static void main(String[] args) {		
		SmartPhone sp = new SmartPhone();
		// 참조변수 sp 로 접근 가능한 SmartPhone 객체의 메서드 : 3개
		sp.call();
		sp.sms();
		sp.kakaoTalk();
		
		if (sp instanceof SmartPhone) {
			System.out.println("sp is a smartphone");
		}
		
		System.out.println("=========================");
		
		if (sp instanceof HandPhone) {
			System.out.println("sp is a HandPhone");
			HandPhone hp = sp;
			hp.call();
			hp.sms();			
		}
		else {
			System.out.println("sp is not a HandPhone");
		}
		
		System.out.println("=========================");
		
		HandPhone hp = new HandPhone();
		hp.call();
		hp.sms();
		
		if (hp instanceof HandPhone) {
			System.out.println("hp is a HandPhone");			
			HandPhone handPhone = hp;
		}
		
		System.out.println("=========================");
		
		if (hp instanceof SmartPhone) {
			System.out.println("hp is a SmartPhone");
		}
		else {
			System.out.println("hp is not a SmartPhone");
//			SmartPhone sp2 = (SmartPhone)hp;
		}
		
		HandPhone hp2 = new SmartPhone();
		hp2.call();
		hp2.sms();
		
		if (hp2 instanceof HandPhone) {
			System.out.println("hp2 is HandPhone");			
		}
		if (hp2 instanceof SmartPhone) {
			System.out.println("hp2 is SmartPhone");
			
		    SmartPhone sp2 = (SmartPhone) hp2;
		    sp2.sms();
		    sp2.kakaoTalk();
		}
		else {
			System.out.println("hp2 is not a SmartPhone");
		}
		
		System.out.println("==========================");
		Child c = new Child();
		
//		Parent p = c;
//		p.parentPrn();
		
		if (c instanceof Parent) {
			System.out.println("c is a Parent");
			Parent p = c;
			p.parentPrn();
		}
		
		Parent p2 = new Parent();
		
		if (p2 instanceof Child) {
			System.out.println("p2 is a Child");
		} else {
			System.out.println("p2 is not a Child");
		}
	}

}

// HandPhone 과 Battery 의 관계는 has-a 관계이다.
class Battery {}

class HandPhone {
	Battery better = new Battery();
	
	public void call() {
		System.out.println("전화!");
	}
	
	public void sms() {
		System.out.println("문자!");
	}
}

// HandPhone 과 SmartPhone 의 관계는 상속관계이다.
class SmartPhone extends HandPhone {
	public void kakaoTalk() {
		System.out.println("카톡!");
	}
}

class Parent {
	public void parentPrn() {
		System.out.println("parentPrn");
	}
}

class Child extends Parent {
	public void childPrn() {
		System.out.println("childPrn");		
	}
}

 

 

상속관계의 오버라이딩

 - 슈퍼클래스의 메서드를 서브클래스에서 오버라이딩 하는 경우
   슈퍼클래스의 메서드는 은닉됨  
 

동적 바인딩 (Dynamic Binding)

 - 상속 관계에서 업캐스팅 후 상속된 메서드를 호출하여 실행할 때
   컴파일(번역) 시점에서의 실행 대상과 실제 실행 단계에서의 실행 대상이 달라지는 것(동적으로 변하는 것)
- 참조 변수의 데이터타입과 무관하게 실제 인스턴스에 따라 실행되는 메서드가 달라짐

public class Ex2 {

	public static void main(String[] args) {
		
		Parent2 p = new Parent2();
		p.parentPrn();
		
		p = new Child2(); // 업캐스팅
		// 참조변수 p 는 Parent2 클래스 타입의 변수이지만
		// 저장된 인스턴스 주소는 Child2 클래스 타입의 인스턴스이다.
		// 따라서, 참조변수 p 를 통해 접근하는 실제 인스턴스는 Child2 이므로
		// p.parentPrn() 메서드를 호출하면 실행되는 메서드도 Child2 의 메서드이다!
		p.parentPrn();
	}

}

class Parent2 {
	public void parentPrn() {
		System.out.println("슈퍼클래스의 parentPrn()");
	}
}

class Child2 extends Parent2 {	
	public void childPrn() {
		System.out.println("서브클래스의 childPrn()");
	}

	@Override
	public void parentPrn() {
		System.out.println("서브클래스에서 오버라이딩 된 parentPrn()");
	}	
}

 

다형성(Polymorphism)

- 하나의 참조변수로 여러 인스턴스를 참조하는 것
= 인스턴스를 다양한 형태로 변환하는 것
= 인스턴스를 업캐스팅하여 슈퍼클래스 타입으로 서브클래스의 멤버 접근

 

public class Ex3 {

	public static void main(String[] args) {
		Circle c = new Circle();
		c.circleDraw();
		
		Rectangle r = new Rectangle();
		r.paint();
		
		Triangle t = new Triangle();
		t.design();
		
		System.out.println("===================");
		c.draw();
		r.draw();
		t.draw();
		System.out.println("===================");
		
		Shape s;		
		s = c;
		s.draw();
		
		s = r;
		s.draw();
		
		s = t;
		s.draw();
	}

}

class Shape { // 도형 클래스
	// 공통적으로 도형을 그릴 수 있는 draw() 메서드 정의
	public void draw() {
		System.out.println("도형 그리기!");
	}
}

class Circle extends Shape {
	public void circleDraw() {
		System.out.println("원 그리기!");
	}

	@Override
	public void draw() {
		System.out.println("원 그리기!");
	}
	
}

class Rectangle extends Shape {
	public void paint() {
		System.out.println("사각형 그리기!");
	}
	
	@Override
	public void draw() {
		System.out.println("사각형 그리기!");
	}
}

class Triangle extends Shape {
	public void design() {
		System.out.println("삼각형 그리기!");
	}
	
	@Override
	public void draw() {
		System.out.println("삼각형 그리기!");
		
	}
}

Output : 

원 그리기!
사각형 그리기!
삼각형 그리기!
===================
원 그리기!
사각형 그리기!
삼각형 그리기!
===================
원 그리기!
사각형 그리기!
삼각형 그리기!

 

 

ex) 다형성은 아래와 같이 메소드의 파라미터를 통해서도 활용할 수 있다.

: 파라미터로 Circle, Rectangle, Triangle 인스턴스 전달 -> Shape 타입으로 업캐스팅됨

public class Ex3 {
	public static void main(String[] args) {		
		drawShape(new Circle());
//		drawShape(new Rectangle());  
		polymorphismDrawShape(new Circle());
		polymorphismDrawShape(new Rectangle());
		polymorphismDrawShape(new Triangle());
	}
	
	public static void drawShape(Circle c) {
		c.draw();
	}
	
	public static void polymorphismDrawShape(Shape s) {
		s.draw();
	}
}

class Shape { // 도형 클래스
	// 공통적으로 도형을 그릴 수 있는 draw() 메서드 정의
	public void draw() {
		System.out.println("도형 그리기!");
	}
}

class Circle extends Shape {
	@Override
	public void draw() {
		System.out.println("원 그리기!");
	}
	
}
(...)

ex) 다형성을 배열에 활용하는 경우 (업캐스팅)

	Circle[] cArr = new Circle[3];
		cArr[0] = new Circle();
//		cArr[1] = new Rectangle();
		
		Shape[] sArr = new Shape[3];
		sArr[0] = new Circle();
		sArr[1] = new Rectangle();
		sArr[2] = new Triangle();
		
		for (Shape shape : sArr) {
			shape.draw();
		}

'Study > Java' 카테고리의 다른 글

[JAVA] 추상(abstract)  (0) 2021.03.09
[JAVA] final 키워드 / 상수(constant)  (0) 2021.03.09
JAVA - getter, setter  (0) 2021.02.09
JAVA - 파일 내 특정 문자열이 포함된 행을 제거  (0) 2021.02.04
JAVA에서의 데이터 타입  (0) 2021.01.11

+ Recent posts