has-a, use-a 관계 정리하기
is-a, has-a 관계는 일방향
자식 객체는 부모 객체를 알지만 (super)
부모 객체는 자식 객체를 모른다
소유하는 객체는 소유당하는 객체를 알지만 (멤버변수)
소유당하는 객체는 소유하는 객체를 모른다
- 다양한 객체를 다루게 되면서 각 객체간 공통점을 어떻게 소거할 것인가, 얼마나 소거할 것인가도 우리의 역할(모델링)
is-a? has-a? use-a? 계층구조? overriding?- 이거 하려면 뭘 해야하는지? - 검색으로도 찾을 수 있는 정보, low level
- 이게 무엇인가? 구조를 알고 설계하는 것 - 쉽게 할 수 없는 내 머리를 써야하는 일, high level
- 자료구조 - 계층구조
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();
}
boolean
상속은 어쩌면 재사용 목적보다, 상위 객체를 보는 것만으로 하위 객체의 정보, 기능을 알 수 있는 것이 목적
p. 247 그림이 부모가 있는 진짜 의미
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);
}
}