[자바JAVA]클래스 : 상속, 메서드 오버라이딩, super()

상속 정의

상속은 객체간의 관계를 표현하는 것.
상속을 왜 사용할까?
프로그램에서 상속은 기존 클래스의 멤버변수와 메서드을 다른 클래스에서 재사용하기 위한 것이다.

  • 상속의 관계에서 물려주는 클래스 : 슈퍼클래스 = 조상클래스 = 모부클래스 = 상위클래스
  • 상속의 관계에서 물려받는 클래스 : 서브클래스 = 자손클래스 = 자식클래스 = 하위클래스

상속 사용방법은 아래와 같다. extends 슈퍼클래스이름으로 작성해주면된다.

1
class 서브클래스이름 extends 슈퍼클래스이름




상속 특징

  • 상속의 장점
    1. 서브클래스는 멤버변수와 메서드를 자신의 것처럼 사용할 수 있기 때문에 코드 절감 효과.
    2. 슈퍼클래스의 코드를 변경하면 모든 서브 클래스들에게도 적용되므로 유지보수성 향상.
  • 상속의 특징 : 단일 상속만 가능
    • 프로그램복잡도를 줄이기 위해서 JAVA는 다중상속을 지원하지않는다.
    • 상속을 여러 슈퍼클래스에서 받을 수 없다.




상속범위

  • 상속대상 : 멤버변수, 메서드
  • 상속제외대상 : 생성자, 초기화블록
    • 생성자는 상속하지않고 super()를 통해 호출한다. 명시적으로 super()를 이용해서 다른 생성자를 호출하는 코드가 없다면 컴파일러는 언제나 슈퍼클래스의 기본 생성자를 호출하는 super()를 생성해 첫 행에 삽입하게 된다. 결론적으로 최상위의 객체인 Object까지 모든 조상객체가 다 만들어지는 구조가 된다.




Object 라이브러리

  • Object는 자바에서 아주 중요한 클래스이며 최상위클래스이다.
  • Object 클래스는 모든 클래스의 조상 클래스로 만약 클래스 선언부에 extends Object생략 가능하다.




메서드 오버라이딩(Method overriding)

  • 슈퍼클래스에서 정의된 기능을 서브 클래스에 적합하게 수정해서 재정의하는 것.
  • 서브클래스의 메서드 오버라이딩을 하면 슈퍼클래스의 메서드를 은닉하고 재정의한다.
    • 은닉한 슈퍼클래스의 메서드에 접근할수있을까?
    • YES!어떻게? super.메서드명();하면된다




메서드 오버라이딩시 똑같아야 하는 것

  • 메서드의 이름은 슈퍼클래스의 메서드 이름과 같아야한다.
  • 매개변수의 개수, 타입, 순서는 슈퍼클래스의 메서드와 같아야한다.
  • 리턴타입은 슈퍼 클래스의 메서드와 같아야한다.




메서드 오버라이딩시 달라도 되는 것

  • 메서드 오버라이딩시 달라도 되는 것
    • 접근지정자 : public > protected > 기본접근지정자(디폴트) > private
    • 하지만 접근지정자가 작아지면 안된다.
  • 메서드오버로딩과 용어헷갈리지않도록 주의!
    • 오버로딩(Overloading) : 같은 이름의 메서드 여러개를 가지면서 매개변수의 유형과 개수가 다르도록 하는 기술
    • 오버라이딩(Overriding) : 상속관계일때 사용하며 같은 이름의 메서드를 가진다. 상위 클래스가 가지고 있는 메서드를 하위 클래스가 재정의해서 사용

아래는 Person 클래스이다.

1
2
3
4
5
6
public class Person{
String name;
public void jump(){
System.out.println("사람 : 뛰기");
}
}

아래는 spider 클래스이다.

1
2
3
4
5
public class Spider {
public void jump(){
System.out.println("스파이터 : 점프");
}
}

이제 오버라이딩해 볼 SpiderMan2 클래스이다.
SpiderMan2는 Person클래스를 상속하고 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class SpiderMan2 extends Person{
Spider spider = new Spider();
boolean isSpider;

@Override //애노테이션
public void jump(){
if(isSpider){
spider.jump();
}else{
System.out.println("스파이더맨2 : 뛰기");
}
}
}

//출력값
거미모드로 변신
스파이터 : 점프
사람모드로 변신
스파이더맨2 : 뛰기




애노테이션(Annotation)

  • @Override
  • 컴파일러등을 위한 주석으로 ‘이 메서드는 재정의한 메서드이니까 메서드 오버라이딩 규칙에 맞지 않으면 오류를 발생시켜라’라는 정보를 컴파일러에게 전달한다.
  • 애노테이션 생략가능.




super키워드

  • 생성자를 만들면 항상 super()로 먼저 슈퍼클래스를 실행한 뒤에 서브클래스를 실행한다.
  • 하나의 파일안에 여러 class를 둘 수 있지만 이럴땐 두가지 규칙이 있다.
    1. 파일명과 동일한 class에만 public을 붙일 수 있다.
    2. 파일명과 동일한 class에만 메인메서드를 넣을 수 있다.
  • 보통 실무에서는 하나의 파일에는 하나의 class만 만든다. 구분하기 편하기때문에.
  • super()는 두가지 기능을 한다.
    1. 조상멤버변수와 메서드를 참조.
    2. 조상의 생성자를 호출.

조상클래스의 생성자를 호출하기 위해 super()가 사용된다.명시적으로 super()를 이용해서 다른 생성자를 호출하는 코드가 없다면 컴파일러는 언제나 슈퍼클래스의 기본 생성자를 호출하는 super()를 생성해 첫 행헤 삽입하게 된다.
이는 결론적으로 최상위의 객체인 Object까지 모든 조상객체가 다 만들어지는 구조가 된다.




this와 super의 차이점

super()와 this()는 둘다 반드시 첫번째 문장에 와야한다.
따라서 둘이 함께 쓰지 못한다.
둘 중 하나만 쓸 수 있다.

  • this가 현재 객체를 참조(나자신)
  • super는 조상 객체를 참조(부모객체)




super예시 : this와 super의 차이점

super()와 this()는 모두 참조변수이다.
아래는 this와 super의 차이점을 설명해주는 super키워드를 사용한 예시이다.
Child는 두개의 멤버변수를 가진다 Parent클래스의 x와 Child클래스의 x.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Parent{
String x = "슈퍼클래스의 멤버변수";
}

class Child extends Parent {
String x = "서브클래스의 멤버변수";

void method(){
String x = "지역변수";
System.out.println("x : " + x);
System.out.println("this.x : " + this.x);
System.out.println("super.x : " + super.x);
}
}

public class ScopeTest {

public static void main(String[] args) {
Child child = new Child();
child.method();
}
}

//출력값
x : 지역변수
this.x : 서브클래스의 멤버변수
super.x : 슈퍼클래스의 멤버변수




super예시 : 순서

아래 코드의 출력값의 순서는 어떻게 될까?

  • 출력값의 순서
    1. main클래스에 따라 MyStudent 클래스를 먼저 실행하는데 extends되어있다 -> MyStydent생성자안에 super()가 생략되어있다.
    2. super()인 Student클래스가 먼저 실행되고 난 후
    3. MyStudent생성자의 println이 실행된다.
  • 파라미터가 있는 생성자를 쓰게 된다면 super()가 에러나지않도록 항상 디폴트생성자를 기재해야한다!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Student{
public Student(){} //디폴트생성자

public Student(int a) { //생성자
System.out.println("슈퍼생성자");
}

}

public class MyStudent extends Student{
public MyStudent(){
//super(); 자동생성되며 생략됨
System.out.println("서브생성자");

}
}

public class Test {
public static void main(String[] args) {
MyStudent ms = new MyStudent(); //객체생성
}
}

//출력값
슈퍼생성자
서브생성자
  • 혹시 아래 코드처럼 super()를 밑에 작성해도 같은 결과가 나올까?
1
2
3
4
5
6
public class MyStudent extends Student{
public MyStudent(){
System.out.println("서브생성자");
super();
}
}

아랫줄에 작성하면 에러Constructor call must be the first statement in a constructor가 발생한다.
super()는 항상 생성자 구현부의 첫번째줄에 있어야한다.

Student 생성자의 생략된 super()는 Object를 상속받고있다.
모든 클래스는 Object를 상속받는다.