1. 자바 상속의 특징 2. super 키워드 3. 메소드 오버라이딩 4. 다이나믹 메소드 디스패치 5. 추상 클래스 6. final 키워드 7. Object 클래스
1. 자바 상속의 특징
상속
부모 클래스와 자식 클래스가 존재하고, 자식 클래스는 부모 클래스의 멤버를 상속받아 사용할 수 있다.
부모 클래스의 private 접근 제한을 갖는 필드와 메소드는 자식이 물려 받지 못한다.
부모와 자식 클래스가 서로 다른 패키지에 있다면 default 접근 제한을 갖는 것들은 물려 받지 못한다.
default 접근 제한 : 같은 패키지에 있는 클래스만 접근 가능한 속성이다.
상속받고자 하는 자식 클래스명 옆에 extends 키워드와 함꼐 상속할 부모 클래스명을 적는다.
자바는 다중 상속을 허용하지 않으므로 부모 클래스로는 한 개의 클래스만 가능하다.
// 부모 클래스
class Parent{
};
// 자식 클래스
class Child extends Parent {
};
2. super 키워드
부모 클래스를 나타내는 키워드다.
자식 클래스의 생성자 첫 줄에 super();을 생성한다.
자식 클래스의 멤버 변수와 부모 클래스의 멤버 변수가 같다면 this와 super는 다른 값을 참조한다.
자식 객체를 생성하면 부모 클래스의 멤버 변수들이 초기화 작업이 수행되야 하므로 자식 클래스의 생성자는 부모 클래스의 생성자를 호출한다 -> super();
class Parent {
public void print() {
System.out.println("부모 클래스의 print() 메소드");
}
}
public class Child extends Parent {
public void print() {
super.print();
System.out.println("자식 클래스의 print() 메소드");
}
public static void main(String[] args) {
Child obj = new Child();
obj.print();
}
}
3. 메소드 오버라이딩
부모 클래스로부터 상속받은 메소드를 자식 클래스에서 재정의하여 사용하는 것이다.
부모 클래스에서 정의된 메소드를 자식 클래스에서 다르게 정의할 때 사용한다.
메소드를 재정의 하기 위해서는 메소드의 형태를 일치시켜야 한다.
메소드 이름, 리턴 타입, 매개 변수 개수, 자료형, 순서
오버라이딩을 하면 자식 클래스에서 재정의한 메소드를 기본적으로 호출한다.
부모 클래스의 메소드 접근하려면 super 키워드를 이용해야 한다.
class Parent {
public void sum(int x, int y) {
int sum = x + y;
System.out.println("합계 : " + sum);
}
}
class Child extends Parent {
public void sum(int x, int y) { // 메소드 오버라이딩
int sum = Math.abs(x + y)
System.out.print("합계 : " + sum);
// super.sum(x, y); // 부모 메소드 호출
}
}
public class Test {
public static void main(String[] args) {
Child sub = new Child();
sub.check();
sub.sum(-5, 1);
}
}
4. 다이나믹 메소드 디스패치
오버라이드 된 베소드에 대한 호출이 런타임에 결정되는 매커니즘이다.
부모 클래스의 타입으로 생성된 변수는 자식 클래스의 객체를 참조할 수 있다. -> 업캐스팅
업캐스팅으로 서로 다른 유형의 객체를 참조할 때 서로 다른 클래스의 메소드가 실행된다.
자식 클래스의 모든 메소드를 부모 클래스에서 호출할 수 있는 것은 아니다.
class A{
void m1(){
System.out.println("Inside A's m1 method");
}
}
class B extends A{
void m1(){
System.out.println("Inside B's m1 method");
}
}
class C extends A{
void m1(){
System.out.println("Inside C's m1 method");
}
}
class Dispatch{
public static void main(String args[]){
A a = new A();
B b = new B();
C c = new C();
A ref;
ref = a;
ref.m1(); // Inside C's m1 method
ref = b;
ref.m1(); // Inside C's m1 method
ref = c;
ref.m1(); // Inside C's m1 method
}
}
다이나믹 변수는 존재하지 않는다. 메소드만 오버라이딩이 가능하므로, 런타임 다형성은 멤버 변수에서 보장되지 않는다.
class A{
int x = 10;
}
class B extends A{
int x = 20;
}
public class Test{
public static void main(String args[]){
A a = new B();
System.out.println(a.x); // 10
}
}
5. 추상 클래스
추상 클래스 정의
여러 클래스들 간에 비슷한 필드와 메소드를 공통적으로 추출해 만든 클래스다.
객체를 생성할 수 없다.
추상 클래스와 실체 클래스 (흔히 작성하는 일반적인 클래스)는 상속 관계를 가진다.
추상 클래스 사용
abstract 키워드를 사용한다.
abstact class 클래스명 {}
public abstract 리턴타입 메소드명();
추상 메서드의 구현부는 작성하지 않고, 상속 받아 오버라이딩 해야한다.
abstract class Animal {
public String kind;
public void breath(){
System.out.println("숨 쉰다.");
}
public abstract void sound();
}
public class Dog extends Animal{
public Dog(){
this.kind = "포유류";
}
@Override
public void sound() {
System.out.println("왈왈!");
}
}
6. final 키워드
final 정의
클래스나 변수에 final을 붙여 변하지 않는 것을 보장한다.
상수를 나타내는 키워드다.
final 변수
final double pi = 3.14;
pi = 3; // error
final 인자
public void func(final int number) {
System.out.println(number);
// number = 2; // error
}
final 클래스
final class Animal {
final String name;
Animal() {
name = "choco";
}
}
class Dog extends Animal() {
// error
}
final 메소드
class Animal {
String name = "choco";
final void printName() {
System.out.println(name);
}
}
class Dog extends Animal {
@Override
String getHello() {
// error
return "See you MJ";
}
}
7. Object 클래스
모든 클래스들의 최상위 조상 클래스다.
모든 클래스는 기본적으로 Object 클래스를 상속받고, Object 클래스에 속한 메소드를 사용할 수 있다.