
코드를 짜다 보면 비슷한 클래스를 여러 개 만들어야 할 때가 있다. 강아지, 고양이, 새는 모두 동물이고 공통된 특성을 가진다. 이런 공통된 부분을 한 곳에 모아두고 재사용하는 게 상속이다.
부모 클래스의 필드와 메서드를 자식 클래스가 물려받는 것이다. extends 키워드를 사용한다.
// 부모 클래스
public class Animal {
String name;
int age;
public void eat() {
System.out.println(name + "이(가) 먹는다.");
}
public void sleep() {
System.out.println(name + "이(가) 잔다.");
}
}
// 자식 클래스
public class Dog extends Animal {
public void bark() {
System.out.println(name + ": 왈왈!"); // 부모의 필드 사용 가능
}
}
Dog dog = new Dog();
dog.name = "멍멍이";
dog.eat(); // 부모의 메서드 사용 가능 → 멍멍이이(가) 먹는다.
dog.bark(); // 자식의 메서드 → 멍멍이: 왈왈!

부모의 메서드를 자식 클래스에서 재정의하는 것이다. 같은 이름이지만 자식만의 방식으로 동작하게 만든다.
public class Animal {
public void sound() {
System.out.println("...");
}
}
public class Dog extends Animal {
@Override
public void sound() { // 부모 메서드를 재정의
System.out.println("왈왈!");
}
}
public class Cat extends Animal {
@Override
public void sound() {
System.out.println("야옹~");
}
}
Animal dog = new Dog();
Animal cat = new Cat();
dog.sound(); // 왈왈!
cat.sound(); // 야옹~
@Override는 생략해도 되지만, 부모 메서드를 재정의한다는 의도를 명확히 하고 컴파일러가 오타를 잡아주기 때문에 붙이는 것이 좋다.
super는 부모 클래스를 가리키는 참조다. 부모의 필드나 메서드에 접근하거나, 부모의 생성자를 호출할 때 쓴다.
public class Animal {
String name;
public Animal(String name) {
this.name = name;
}
public void introduce() {
System.out.println("나는 동물이고 이름은 " + name + "이다.");
}
}
public class Dog extends Animal {
String breed;
public Dog(String name, String breed) {
super(name); // 부모 생성자 호출 (반드시 첫 번째 줄)
this.breed = breed;
}
@Override
public void introduce() {
super.introduce(); // 부모의 introduce() 호출
System.out.println("견종은 " + breed + "이다.");
}
}
private 멤버에는 접근할 수 없다.Object를 상속한다.상속은 공통된 코드를 부모에 두고 자식이 물려받아 재사용하는 것이다. 코드 중복을 줄이고, 공통 타입으로 묶어 다형성을 활용할 수 있게 해준다.