클래스는 데이터를 사람이 생각하는 방식대로 기능하도록 가공하는 것이라 볼 수 있다. 자동차 클래스라면 제조사, 마력, 연비, 인원수를 인스턴스로, 주행, 주유 등을 메서드로 가지고 있을 것이며, 벌 클래스면 성별, 크기 등을 인스턴스로, 수분, 비행, 생식, 공격 등을 메서드로 가질 것이다. 한편으로, 날벌레 클래스는 인스턴스와 메서드의 많은 부분이 벌과 겹칠 것이다. 이러한 경우, 날벌레와 벌 클래스를 따로 작성하되, 각각의 메서드를 비슷하게 작성하는 것은 메모리의 낭비이다. Java와 많은 프로그래밍 언어는 이와 같은 낭비를 막기 위해 상속 개념을 지원한다.
상속이라는 단어가 내포하고 있는 의미대로, 대부분의 경우 큰 범주의 상위 클래스를 하위 클래스가 상속하면, 상위 클래스에 작성된 인스턴스와 메서드를 하위 클래스 객체가 사용할 수 있다.
캡슐화에 따르면, 클래스의 인스턴스는 외부에서 직접 접근해서는 안된다. 하지만, 상속에 따르면, 하위 클래스는 상위 클래스의 인스턴스를 사용할 수 있어야 한다. 그렇기 때문에, public/private modifier로는 원하는 목적을 달성할 수 없다.
이를 위해 protected modifier가 필요하다. protected를 사용하면, 외부에서는 인스턴스에 접근할 수 없지만, 하위 클래스는 접근이 허가된다.
상속을 통해 하위 클래스는 인스턴스 뿐 아니라, 메서드 또한 사용할 수 있다. 하지만, 상위 클래스와 하위 클래스가 온전히 같지 않고, 상위 클래스에서 사용하는 메서드의 기능과 하위 클래스에서 필요로하는 메서드의 기능이 동일하지 않은 경우에는 빌리는 것으로는 기능이 모자라다.
이런 경우, 하위 클래스에서 상위 클래스에 작성한 메서드와 이름은 동일하지만 기능이 수정된 메서드를 새로 작성할 수 있다. 이 경우, 상위 클래스의 객체는 상위 클래스의 메서드가 동작하지만, 하위 클래스의 객체는 새로 작성한 하위 클래스의 메서드가 동작한다.
public class Insect{
protected double weight;
public Insect(){
this(1.0);
}
public Insect(double weight){
this.weight = weight;
}
public void move(){
System.out.println("Move 1 tile");
}
}
public class Fly extends Insect{
protected double speed;
public Fly(){
this(10.0);
}
public Fly(double weight, double speed){
super(weight);
this.speed = speed;
}
public void move(){
String answer = String.format("move %d tile", this.getSpeed());
System.out.println(answer);
}
public double getSpeed(){
return this.speed;
}
}
이상의 예제에서, Fly 클래스는 Insect 클래스를 상속한다. 그래서 부모 클래스의 weight 인스턴스를 사용할 수 있고, 생성자는 일부 공유한다. 한편, move 메서드의 경우, 부모 클래스와 자식 클래스는 같은 이름의 메서드를 공유하지만, 출력값이 조금 다르다. 이때, 자식 객체로 move메서드를 이용하면 자식의 메서드가, 부모 객체로 move 메서드를 이용하면 부모의 메서드를 호출한다.
예제에서 작성한 super()는 this()와 비슷하게 참조 연산자이지만, 부모 클래스를 참조한다는 차이가 있다.
final modifier는 인스턴스 변수, 메서드, 클래스에 적용할 수 있다.
인스턴스 변수에 final을 적용할 경우, 클래스 내부에서 마치 상수와 같은 역할을 수행한다. 객체를 생성할 때, 모든 객체는 final 인스턴스에 이미 할당된 값을 가지게 된다. 그렇기에 static 또한 같이 적용하는 경우가 있다. 또한, 메서드 등 클래스 멤버를 통해서 변형이 불가능하기 때문에, final 인스턴스 변수는 캡슐화와 연관이 있다.
메서드와 클래스에 final을 적용하는 경우, 캡슐화가 아닌 상속과 연관이 있다. 인스턴스를 상수로 만들어 변형이 불가능하도록 만드는 것처럼, 메서드에 적용하면 자식 클래스는 메서드를 덮어 쓸 수 없다. 클래스에 적용할 경우, 해당 클래스는 부모클래스를 가질 수 없다.
이상의 내용은 edx 플랫폼을 통해 GTx에서 제공하는 Introduction to Object-Oriented Programming with Java 강의의 내용을 개인적으로 정리한 것입니다. 그렇기 때문에, 부정확한 내용 혹은 잘못 이해하고 있는 내용이 있을 수 있으니 양해 부탁드립니다.