다형성은 한 타입의 참조변수를 통해 여러 타입의 객체를 참조할 수 있도록 만든 것을 의미한다.
-> 상위 클래스 타입의 참조변수를 통해서 하위 클래스의 객체를 참조할 수 있도록 허용한 것
GirlFriend
를 참조변수의 타입으로 지정해주어야 하지만, 그러지 않고 상위 클래스 Friend
를 타입으로 지정해주고 있다. 상위 클래스 타입의 참조변수로 하위 클래스의 객체를 참조하는 것을 보여주는 예시임.
상위 클래스인 Friend
타입으로 하위 클래스 GirlFriend
를 참조하는 것은 가능하지만, 그 반대로 하위 클래스 GirlFriend
의 타입으로 상위 클래스 객체 Friend
를 참조하는 것은 불가능하다.
그 이유는 실제 객체인
Friend
의 멤버 개수보다 참조변수friend1
이 사용할 수 있는 멤버 개수가 더 많기 때문이다.
instanceof
연산자는 참조변수의 타입 변환, 즉 캐스팅이 가능한 지 여부를 oolean
타입으로 확인할 수 있는 자바의 문법요소.참조_변수 instanceof 타입
참조_변수 instanceof 타입
입력했을 때 리턴 값이 true가 나오면 참조 변수가 검사한 타입으로 타입 변환이 가능하며, 반대로 false가 나오는 경우에는 타입 변환이 불가능하다. 만약에 참조 변수가 null인 경우에는 false를 반환한다.추상화의 핵심적인 개념은 공통성과 본질을 모아 추출하는 것을 의미함. 추상화와는 반대로 기존 클래스들의 공통적인 요소들을 뽑아서 상위 클래스를 만들어 내는 것이라고 할 수 있다.
공통적인 속성과 기능을 모아서 정의해주면 코드의 중복을 줄일 수 있고, 보다 효과적으로 클래스 간의 관계를 설정할 수 있으며, 유지/보수가 용이해진다.
자바에서 abstract라는 단어가 내포하는 의미는 ‘미완성'이라고 할 수 있다.
abstract
는 주로 클래스와 메서드를 형용하는 키워드로 사용되는데, 메서드 앞에 붙은 경우를 ‘추상 메서드(abstract method)’, 클래스 앞에 붙은 경우를 ‘추상 클래스(abstract class)’라 부른다.
어떤 클래스에 추상 메서드가 포함되어있는 경우 해당 클래스는 자동으로 추상 클래스가 된다.
abstract class AbstractExample { // 추상 메서드가 최소 하나 이상 포함돼있는 추상 클래스
abstract void start(); // 메서드 바디가 없는 추상메서드
}
추상 클래스를 만드는 이유 ?
추상 클래스는 상속 관계에 있어 새로운 클래스를 작성하는데 매우 유용함.
-> 추상 클래스를 사용하면 상속을 받는 하위 클래스에서 오버라이딩을 통해 각각 상황에 맞는 메서드 구현이 가능하다는 장점이 있다.
추상 클래스는 자바 객체지향 프로그래밍의 마지막 기둥인 추상화를 구현하는데 핵심적인 역할을 수행함.
-> 만약 여러 사람이 함께 개발하는 경우, 공통된 속성과 기능임에도 불구하고 각각 다른 변수와 메서드로 정의되는 경우 발생할 수 있는 오류를 미연에 방지할 수 있다.
final
키워드는 그 위치에 따라 의미가 달라진다.위치 | 의미 |
---|---|
클래스 | 변경 또는 확장 불가능한 클래스, 상속 불가 |
메서드 | 오버라이딩 불가 |
변수 | 값 변경이 불가능한 상수 |
final class FinalEx { // 확장/상속 불가능한 클래스
final int x = 1; // 변경되지 않는 상수
final int getNum() { // 오버라이딩 불가한 메서드
final int localVar = x; // 상수
return x;
}
}
final
제어자가 추가되면 이제 해당 대상은 더이상 변경이 불가하거나 확장되지 않는 성질을 지니게 된다.인터페이스는 기본적으로 추상 메서드와 상수만을 멤버로 가질 수 있다는 점에서 추상 클래스에 비해 추상화 정도가 더 높다고 할 수 있다.
일반 클래스와 다르게, 내부의 모든 필드가 ublic static final
로 정의되고, static
과 default
메서드 이외의 모든 메서드가 public abstract
로 정의된다는 차이가 존재한다. 모든 인터페이스의 필드와 메서드에는 위의 요소가 내포되어있기 때문에 명시하지 않아도 생략이 가능하다.
public interface InterfaceEx {
public static final int rock = 1; // 인터페이스 인스턴스 변수 정의
final int scissors = 2; // public static 생략
static int paper = 3; // public & final 생략
public abstract String getPlayingNum();
void call() //public abstract 생략
}
implements
키워드를 사용한다. class 클래스명 implements 인터페이스명 {
... // 인터페이스에 정의된 모든 추상메서드 구현
}
어떤 클래스가 어떤 인터페이스를 구현한다는 것은 그 인터페이스가 가진 모든 추상 메서드들을 해당 클래스 내에서 오버라이딩하여 바디를 완성한다라는 의미를 가진다.
Object 클래스
와 같은 최고 조상이 존재하지 않는다.class ExampleClass implements ExampleInterface1, ExampleInterface2, ExampleInterface3 {
... 생략 ...
}
클래스에서 다중 상속이 불가능했었던 핵심적인 이유는 만약 부모 클래스에 동일한 이름의 필드 또는 메서드가 존재하는 경우 충돌이 발생하기 때문이다. 반면 인터페이스는 애초에 미완성된 멤버를 가지고 있기 때문에 충돌이 발생할 여지가 없기 때문에 안전하게 다중 구현이 가능하다.
특정 클래스는 다른 클래스로부터의 상속을 받으면서 동시에 인터페이스를 구현할 수 있다.
인터페이스도 추상 클래스처럼 자바에서 추상화를 구현하는 데 활용된다는 점에서 동일하지만, 추상클래스에 비해 더 높은 추상성을 가진다는 점에서 큰 차이가 있다.
추상 클래스를 설계가 모두 끝나지 않은 “미완성 설계도" 에 비유할 수 있다면, 인터페이스는 그보다 더 높은 추상성을 가지는 가장 기초적인 “밑그림" 에 빗대어 표현할 수 있다.
추상 클래스는 메서드 바디가 없는 추상 메서드를 하나 이상 포함한다는 점 외에는 기본적으로 일반 클래스와 동일하다고 할 수 있다.
반면 인터페이스는 기본적으로 추상 메서드와 상수만을 멤버로 가질 수 있다는 점에서 추상 클래스에 비해 추상화 정도가 더 높다고 할 수 있다.