오리라는 이름을 가진 클래스를 만들어서 오리의 기본적인 행동을 할 메서드를 구현한 다음 청둥오리와 물오리 클래스에서 각각 상속받아 사용하게 하면 아까전에 생겼던 중복 코드를 줄일 수 있을 것이다. extends 키워드를 사용하면 된다.class Child extends Parent {
// ...
}
부모 클래스, 상속받는 클래스를 자손 클래스라 한다.조상 클래스 : 부모(parent) 클래스, 상위(super) 클래스, 기반(base) 클래스
자손 클래스 : 자식(child) 클래스, 하위(sub) 클래스, 파생된(derived) 클래스

[이미지 출처] http://www.tcpschool.com/java/java_inheritance_concept
extends인 이유이기도 하다. 주의사항:
생성자와 초기화 블럭은 상속되지 않는다. 멤버만 상속된다.
자손 클래스의 멤버 개수는 조상 클래스보다 항상 같거나 많다.
오버라이딩이라 한다. 다중상속이 가능하지만 자바에서는 오직 단일상속만 허용한다. powerOn()이라는 메서드가 있다면 자손 클래스인 클래스 C에서는 어느 부모 클래스의 powerOn()을 상속받는 것인지 모호해지기 때문이다. 이름을 바꿔가면서 구별하는 것도 한계가 있고... 여러가지로 불편한 점이 많기 때문에 자바에서는 단일상속만 허용한다.Object 클래스는 모든 클래스의 최상위에 있는 조상 클래스이다. 자바에서 사용되는 클래스들의 부모를 찾아찾아 거슬러 올라가면 마지막엔 Object 클래스가 있다. 그래서 toString()이나 equals()와 같은 메서드들을 따로 정의하지 않고 그냥 사용할 수 있다. 왜냐면 모두 Object 클래스에 정의되어 있기 때문이다. 여러 가지 형태를 가질 수 있는 능력을 의미한다. 조상클래스 타입의 참조변수로 자손클래스의 인스턴스를 참조할 수 있도록 하였다는 것이다. class Parent {
}
class Child extends Parent {
}
Parent P = new Child(); // 컴파일 잘 됨
Parent에 정의된 멤버만 사용할 수 있는데 그 수가 자손 클래스인 Child에 정의된 멤버의 수보다 적기 때문에 없는 것을 사용할 위험은 없기 때문이다. Child c = new Parent(); // 컴파일 에러
하지만 반대 경우는 안 된다.
왜냐면 상속받은 자식 클래스인 Child의 멤버 개수가 부모 클래스인 Parent보다 많기 때문에 Parent에 없는 멤버를 사용하려 할 수 있기 때문이다. 실제 내용물이 없는 것을 참조하면 당연히 NullPointerException이 발생할 것이다.
이러한 특징은 메서드의 매개변수에도 적용해서 더욱 유연한 코드를 작성할 수 있다.
class Product {
int price;
int bonusPoint;
}
class Tv extends Product {}
class Computer extends Product {}
class Audio extends Product {}
class Buyer {
int money = 1000;
int bonusPoint = 0;
}
Buyer 클래스에 물건을 구입하는 메서드를 추가하는 경우를 생각해 보자.void buy(Tv t) {
money -= t.price;
}
void buy(Computer c) {
money -= c.price;
}
void buy(Audio a) {
money -= a.price;
}
buy() 메서드를 만들어줘야 한다. 여간 귀찮고 유지보수도 힘든 것이 아니다. 여기에 매개변수의 다형성을 적용하면 중복 코드를 줄이고 유지보수도 훨씬 쉬운 코드로 작성할 수 있다. void buy(Product p) {
money -= p.price;
}
이렇게 쓰면 Product를 상속받는 모든 클래스들의 참조변수를 처리할 수 있다. 상품의 수가 늘어나도 문제가 없다.
이것을 좀 더 확장해 보면 여러 종류의 객체를 배열에도 담을 수 있게 된다.
Product p[] = new Product[3];
Product[0] = new Tv();
Product[1] = new Computer();
Product[2] = new Audio();