class Animal{ public void move() { "동물" 출력 } }
class Tiger extends Animal { public void move() { "호랑이" 출력 } }
public class Test { .. public void moveAnimal(Animal animal) { animal.move() } }
가상 메서드 원리에 따라 호출되는 메서드는 자료형의 클래스의 메서드가 아니라 실제 인스턴스의 메서드다.
-> 어떤 매개변수가 넘어오더라도 자료형은 모두 Animal형으로 변환하지만, animal.move()는 실제 인스턴스에 따라 출력이 달라진다.
다형성의 장점?
1) 프로그램의 확장성
2) 유지보수성
: 각 자료형에 따라 다르게 구현한다면 코드는 복잡해짐, 상위에서 공통 메서드 구현하고 하위에서 추가요소를 덧붙여 구현하면 각 클래스의 여러가지 구현도 할 수 있고(=확장성) 유지보수도 하기 쉬워짐
만약 재정의한 메서드가 가상 메서드 방식에 의해 자동으로 호출되지 않는다면 if-else if 문을 사용해서 따로 구현해야 할 것이다. 게다가 새로운 조건이 필요한 경우에는 또 다른 조건으로 구현해야 하기 때문에 코드의 유지보수가 어려워질 수 있따.
상속은 언제 사용할까?
IS-A (is a relationship; inheritance) : 일반적인 개념과 구체적인 개념
즉 일반 클래스를 점차 구체화하는(=확장되는) 상황에서 상속을 사용하는 것이다.
이질적인 클래스 간에는 상속을 사용하지 않는 것이 좋다
어떤 경우에 상속을 사용하지 말아야 할까?
HAS-A (has a relationship; association) : 한 클래스가 다른 클래스를 소유한 관계
예) Subject는 Student에 포함되는 것이기 때문에 상속을 사용해선 안됨
class Student { Subject majorSubject; }
알고가자!) 상속을 재사용의 개념으로 이해해선 안된다!
재사용할 수 있는 코드가 있다고 해서 무조건 상속을 하면 클래스 간의 결합도가 높아져서 오히려 상위 클래스의 변화가 하위 클래스에 미치는 영향이 커지게 된다. 결합도는 낮추고 응집도는 높이는 방향으로 소프트웨어는 설계되어야 함!
알고가자!) 여러 클래스를 한번에 상속받을 수는 없다. extends 뒤에는 상위 클래스 '하나만' 가능하다.
6장 클래스와 객체2의 연습문제를 풀다보니 저번학기에 들은 데이터베이스 시간에 과제를 했던 게 생각났다. 제공된 요구사항을 바탕으로 ER다이어그램을 만드는 게 과제였는데 어떤 걸 엔티티로 해야 할지 관계로 짜야 할지 계속 고민하다가 눈물 날 뻔한 과제였다. 그래서 어찌어찌 내긴 했는데 교수님께서 올려주신 정답과는 다른 방식으로 짰다...
교수님께선 ER다이어그램을 짜는데엔 정답은 없다고 하셨지만 과연 내가 만든 게 효율적인 답안이었을진...
Student 생성자를 만들 때 그 안에 분리했던 Subject 클래스의 생성자도 추가해주어야 한다. (생성자는 클래스가 생성될 때 자동으로 호출된다)
그래야 Test에서 Park.math.Subjectname이나 Park.math.scorePoint를 선언할 수 있게 된다.
package ch5;
public class Student3 {
int studentID;
String studentName;
Subject Korean;
Subject math;
public Student3() {
Korean = new Subject("국어");
math = new Subject("수학");
}
public Student3(int id, String name) {
studentID = id;
studentName = name;
Korean = new Subject("국어");
math = new Subject("수학");
}
}
Subject 클래스
package ch5;
public class Subject {
String SubjectName;
int scorePoint;
public Subject(String name) {
SubjectName = name;
}
}
Test 클래스
package ch5;
public class StudentTest {
public static void main(String[] args) {
Student3 Park = new Student3(201935, "박정미");
Park.math.scorePoint = 50;
System.out.println(Park.studentName);
System.out.println(Park.math.SubjectName);
System.out.println(Park.math.scorePoint);
Student Jeong = new Student();
Jeong.setStudentName("쩡미");
System.out.println(Jeong.getStudentName());
}
}