[객체지향][다형성] 국비 27일차

포키·2022년 10월 28일
0

국비과정

목록 보기
24/73

has-a, use-a 관계 정리하기

is-a, has-a 관계는 일방향
자식 객체는 부모 객체를 알지만 (super)
부모 객체는 자식 객체를 모른다
소유하는 객체는 소유당하는 객체를 알지만 (멤버변수)
소유당하는 객체는 소유하는 객체를 모른다

  • 다양한 객체를 다루게 되면서 각 객체간 공통점을 어떻게 소거할 것인가, 얼마나 소거할 것인가도 우리의 역할(모델링)
    is-a? has-a? use-a? 계층구조? overriding?
  • 이거 하려면 뭘 해야하는지? - 검색으로도 찾을 수 있는 정보, low level
  • 이게 무엇인가? 구조를 알고 설계하는 것 - 쉽게 할 수 없는 내 머리를 써야하는 일, high level
  • 자료구조 - 계층구조

다형성

Java의 다형성 정의

  • 다형성 : 많은poly + 모양morph
    하나의 객체가 많은多 형태type로 나타날 수 있는 것 = 다형성이 성립한다.
    (-> 참조형의 형변환이 일어나는 것)
B b = new B();
A a = b;
Object o = b;
  • O ← A ← B ... 'is-a 관계'가 성립할 때,
    (= O가 A를 포괄하는 상위개념, A가 B를 포괄하는 상위개념)
    new B()로 생성된 객체는 B b, A a, O o로 부를 수 있다.
    (= 상위개념의 이름으로 부를 수 있다.)

  • 다형성의 조건은 'is-a' 관계
    ('is-a' 관계이지만 상속 관계가 아닌 경우도 있다는 점에 유의!)

  • 자바의 다형성
    자바에서 프로그램을 구성하는 것은 객체
    -> 자바의 다형성이란 '객체가 다양한 타입을 가지는 것‘이다 (즉, 객체 기준)
    -> 함수로 구성되는 언어에서는 함수가 다양한 형태를 지니는 것(=오버로딩)이 다형성이 됨
class A {
	public void methodA() {	
    }
}
class B {
	public void methodB() {
    }
}
class Ex2 {
	public static void main(String[] args) {
    	A a = new B();
        
        a.methodA();
        a.methodB();		// 컴파일 에러 - type A의 변수 a를 사용한다면, type A의 정의 내에서 사용해야 한다.
    }
}

복습
Type : 크기 + 종류를 의미

  • A는 methodA()를 할 수 있는 객체로 정의 = A의 type
    B는 methodA(), methodB()를 할 수 있는 객체로 정의 = B의 type
    a는 A type의 변수 -> A type이란 methodA()를 할 수 있는 객체 -> methodB()는 정의에서 벗어나므로 컴파일 에러

  • 형변환
    'is-a' 관계가 성립할 때 가능
    작은 개념(하위 개념)에서 큰 개념(상위 개념)으로 변환은 문제없이 가능 : 상향형변환upcasting
    큰 개념에서 작은 개념으로 변환은 '(상위개념)' 붙여서 강제형변환 필요 : 하향형변환downcasting

  • 오버라이딩할 경우 메서드는 언제나 자식 객체의 메서드가 나온다
    (물리적으로 같은 메서드 - 오류나지 않음)
    (데이터를 찾는 순서는 설령 A 객체로 인지하더라도(참조변수가 A타입이더라도) B 객체부분부터 시작, 다형성으로 객체를 A로 착각하더라도 읽는 순서가 달라지지는 않음)

		A a = new B();
  • 자식 객체가 부모 객체로 살다 다시 자식 객체로 돌아갈 수는 있다 (정확히는 참조변수의 변화)
    하지만 부모 타입이 자식 타입으로 변환될 수는 없다
    	A a = new A();
		B b = (B) a;
        // 컴파일 에러는 나지 않지만, 실행 중 에러가 발생함 (runtime error)

형식상의 문제는 없지만, 실제로 B 객체에 존재해야 하는 데이터가 없으므로 에러가 나는 것

연산자 instanceof

: 참조변수의 type을 식별하는 연산자 instanceof

  • 형변환의 안정성을 위해 사용
	if(obj instanceof Dog){
    	obj.bark();
    }
  • 변수 obj가 클래스 Dog의 참조변수이다.
  • 결과는 boolean
  • instanceof를 사용해야만 한다면 하겠지만, 객체를 확인한 후 명령을 내려야 한다면 overriding을 사용하는 것이 더 적절할 것. ('슈퍼맨 클래스' 만들지 않기)
  • 판별할 필요가 없도록 만드는 것이 더 나음

동적바인딩

  • 상위 객체에서는 정의만 하고, 하위 객체에서 직접 행위하게 함으로써, '행위의 책임을 하위 객체가 지도록 하는 것'이 더 좋다.

상속은 어쩌면 재사용 목적보다, 상위 객체를 보는 것만으로 하위 객체의 정보, 기능을 알 수 있는 것이 목적

  • 하위 객체의 기능을 상위 객체에서 미리 정의해주는 것이 약속 = 위만 봐도 됨
    미리 설명, 메서드명 통일,

p. 247 그림이 부모가 있는 진짜 의미

기타

  • 패러미터를 전부 Object로 하면?
    존재하는 모든 객체가 들어올 수 있다 -> 의미가 없다.
    -> 들어오는 놈 예측 불가,
  • Object를 패러미터로 받을 수 있는 건 Object밖에 없다.

final 키워드

  • final 변수 : 앞으로 변수의 값을 변경하지 않음
  • final 메서드 : 오버라이드 금지
  • final 클래스 : 상속 금지
  • 일반적으로 외부 자원과 관련 있음 (??? 모르겠다.)
  • 아직은 거의 쓸 일 없을 것

Quiz1

  1. is-a 추가 (BasicShape <- 삼각형/사각형)
  2. has-a 이용 (ShapeInfo <- BasicShape <- 삼각형/사각형)
class Shape {
	public int getArea() {
		return 0;
	}
	@Override
	public String toString() {
		return "area : " + getArea();
	}
}
class Circle extends Shape {
	private int radius;
	public Circle(int radius) {
		setRadius(radius);
	}
	public int getRadius() {
		return radius;
	}
	public void setRadius(int radius) {
		this.radius = radius;
	}

	@Override
	public int getArea() {
		return (int) (radius * radius * 3.14);
	}
	@Override
	public String toString() {
		return "<Circle>\nradius : " + radius + "\n" + super.toString();
	}
}
class Triangle extends Shape {
	private int base;
	private int height;
	public Triangle(int base, int height) {
		setBase(base);
		setHeight(height);
	}
	public void setBase(int base) {
		this.base = base;
	}
	public void setHeight(int height) {
		this.height = height;
	}
	public int getBase() {
		return base;
	}
	public int getHeight() {
		return height;
	}
	
	@Override
	public int getArea() {
		return (int) (base * height * 0.5);
	}
	@Override
	public String toString() {
		return "<Triangle>\nbase : " + base + ", height : " + height + "\n" + super.toString();
	}
}
class Rectangle extends Shape {
	private int width;
	private int height;
	public Rectangle(int width, int height){
		setWidth(width);
		setHeight(height);
	}
	public int getWidth() {
		return width;
	}
	public int getHeight() {
		return height;
	}
	public void setWidth(int width) {
		this.width = width;
	}
	public void setHeight(int height) {
		this.height = height;
	}

	@Override
	public int getArea() {
		return width * height;
	}
	@Override
	public String toString() {
		return "<Rectangle>\nwidth : " + width + ", height : " + height + "\n" + super.toString();
	}
}
class Quiz1 {
	public static void main(String[] args) {
		Shape c = new Circle(2);
		Shape t = new Triangle(3,4);
		Shape r = new Rectangle(3,4);
		
		System.out.println(c);
		System.out.println(t);
		System.out.println(r);
	}
}
profile
welcome

0개의 댓글