1. 인터페이스와 다형성
상속과 다형성을 위해 Animal 클래스가 분명히 필요합니다.
하지만 Animal 클래스 자체가 아닌 덜 추상적인 Animal 클래스의
하위클래스의 인스턴스만 만들 수 있게하면 좋겠습니다.
어떤 클래스의 인스턴스를 만들 수 없게 하는 간단한 방법.
- 클래스를 abstract로 지정하면 컴파일러에서 그 유형의 인스턴스를
만드는 코드를 허용하지 않는다.
abstract class Canine extends Animal{
public void roam(){
}
}
2. 추상 클래스는 확장하지 않으면 거의 쓸모도 없고, 가치도 없고, 삶의 목적도 없습니다.
추상 클래스를 만들었을 때 실제 실행 중에 일을 처리하는 것은
그 추상 클래스의 하위클래스 인스턴스입니다.
3. 추상 메소드
클래스뿐만 아니라 메소드로 abstract로 지정할 수 있습니다.
추상 클래스는 반드시 확장해야 하는 클래스를 의미합니다.
추상 메소드는 반드시 오버라이드해야하는 메소드를 의미합니다.
- 추상 메소드를 만들 때는 클래스도 반드시 추상 클래스로 만들어야 합니다.
추상 클래스가 아닌 클래스에 추상 메소드를 집어 넣을 수는 없습니다.
- 추상 메소드를 만드는 이유는 실제 메소드 코드를 전혀 집어넣지는 않았더라도
일련의 하위클래스를 위한 규약의 일부를 정의하기 위한 것입니다.
- 추상 메소드에는 몸통이 없습니다. 다형성을 위해 존재할 뿐입니다.
즉, 그 상속 트리에서 처음으로 등장하는 구상 클래스에서
모든 추상 메소드를 구현해야 합니다.
추상 메소드를 구현한다는 것은 메소드의 본체를 만들어야 한다는 것을 의미합니다.
public class MyAnimalList{
private Animal[] animals = new Animal[5];
private int nextIndex = 0;
public void add(Animal a){
animals[nextIndex] = a;
nextIndex++;
}
}
public class AnimalTestDrive{
public static void main(String [] args){
MyAnimalList list = new MyAnimalList();
Dog a = new Dog();
Cat c = new Cat();
list.add(a);
list.add(c);
}
}
4. Object 클래스
자바 입장에서 모든 객체에 있어야 할 행동에는 어떤 것이 있을지 생각해봅시다.
- 어떤 객체가 다른 객체와 같은지 알아내기 위한 메소드
- 그 객체의 실제 클래스 유형을 알려주는 메소드
- 객체를 해시테이블에 집어넣은 데 필요한 객체의 해시코드를 알려주는 메소드
- 그 객체의 내용에 해당하는 String 메시지를 출력하는 메소드
- Object 클래스는 주로 두 가지 용도로 사용됩니다.
하나는 임의 클래스에 대해 어떤 작업을 하는 메소드를 만들 때
다형적 유형으로 사용하는 경우이고,
다른 하나는 자바에 있는 모든 객체에서 실행 중에 필요한 진짜 메소드 코드를
제공하기 위해서 입니다. (Thread 관련 메소드는 중요합니다.)
자바는 유형을 철저하게 따지는 언어기 때문에 컴파일러에서 어떤 객체에 대해
메소드를 호출할 때 그 객체가 주어진 메소드에 대해 응답을 할 수 있는지 따져봅니다.
즉 그 레퍼런스 유형의 클래스에 해당 메소드가 있는 경우에만 객체 래퍼런스에 대해
메소드를 호출할 수 있습니다.