this와 super

this 예약어

non-static 영역에서만 사용 가능한 예약어로, 현재 실행중인 객체가 자기 자신을 가리킬 때 씀

this.

  • 지역 변수(매개 변수 등)와 멤버 변수(인스턴스 변수)를 구분하여 객체 자신인 멤버 변수를 가리키는 목적
  • 자기 자신의 객체를 메서드의 매개변수로 전달하거나 return 하기 위한 목적
  • 멤버 변수가 현재 클래스에 존재하지 않는다면 부모 클래스에서 찾음
Java
public class Person {
    private String name;   // 멤버 변수
    private int age;

    // 생성자에서 활용
    public Person(String name, int age) {  // 지역 변수
        this.name = name;  // 멤버 변수 가리킴
        this.age = age;
    }

    // setter에서 활용
    public void setName(String name) {  // 지역 변수
        this.name = name;  // 멤버 변수 가리킴
    }
}

this()

  • 생성자 내부에서 자신의 또 다른 생성자(오버로딩된 생성자)를 메서드처럼 호출하여 사용할 때 자신의 또 다른 생성자(오버로딩된 생성자)를 가리키는 목적
  • 오버로딩된 생성자가 없다면 사용 불가
  • 생성자 내에서 가장 상위 라인에 한 번만 존재할 수 있음
  • 한 생성자 안에서 super()와 함께 쓸 수 없음(3번 위배)
Java
public class Person {
    private String name;   // 멤버 변수
    private int age;

    // 생성자에서만 활용
    public Person(String name) {  // 지역 변수
        this.name = name;  // 멤버 변수 가리킴
    }

    public Person(String name, int age) {  // 지역 변수
        this(name);       // 오버로딩된 생성자 가리킴
        this.age = age;   // 멤버 변수 가리킴
    }
}

super 예약어

non-static 영역에서만 사용 가능한 예약어로, 현재 실행중인 객체가 자신의 부모 클래스의 객체를 가리킬 때 씀

super.

  • 자식 클래스가 부모 클래스와 동일한 이름을 가진 멤버를 가지고 있을 때, 자신의 멤버와 구분하여 부모의 멤버를 가리키기 위한 목적
  • 부모 클래스에 동일한 이름의 멤버가 존재하지 않을 경우 사용 불가
  • super를 사용한다고 객체를 여러개 생성하는 것이 아님. 자기 자신 타입의 단 하나의 객체를 생성한 뒤, 자기 자신 객체에서 부모 부분을 찾아가 해당 멤버를 사용하는 것
  • 하지만, 멤버 변수의 경우 오버라이딩 개념이 없으므로 굳이 자식 클래스에서 부모 클래스와 동일한 데이터 타입과 이름을 가진 멤버 변수를 만들어 사용할 필요가 없음(다소 부적절한 사용, 그냥 부모 클래스의 멤버 변수를 사용하면 됨)
Java
class Employee {
    public String name = "capo";
    public String dept = "Accounting";

    static void getDept() {
        System.out.println(skill);
    }
}

class Engineer extends Employee{
    public String dept = "IT";   // 부모와 동일한 멤버 변수

    // 자식의 메서드가 인스턴스 메서드라면 부모를 상속받은 자신의 객체에서 부모 멤버 접근하는 구조
    void printDept1() {
        getDept();    // (= this.getDept() = super.getDept())
    }

    // 자식의 메서드가 static 메서드라면 객체 생성 안했으므로 부모 클래스 멤버를 사용하는 구조(즉, getDept()를 사용하기 위해 Employee를 상속받을 필요 없음)
    static void printDept2() {
        getDept();    // (= Employee.getDept(), != super.getDept())
    }

    public static void main(String[] args) {
        System.out.println("this.dept : " + this.dept);  // 자신의 멤버 변수값 IT
        System.out.println("super.dept : " + super.dept);  // 부모의 멤버 변수값 Accounting

        Engineer eg = new Engineer();
        eg.printDept1();     // Accounting (상속받은 부모의 객체에 접근하여 메서드 호출)
        eg.printDept2();     // Accounting (상속관계 없어도 가능. Employee 클래스의 메서드 호출)
    }
}

super()

  • 자식 클래스에서 부모 클래스의 생성자를 메서드처럼 호출하여 사용할 때 부모 클래스의 생성자를 가리키는 목적
  • 부모 클래스에 해당 매개변수 구조를 구현한 생성자가 존재하지 않는다면 사용 불가
  • 기본적으로 모든 클래스는 Object 클래스를 상속받고 있으므로 모든 자식클래스의 디폴트 생성자에는 암묵적으로 super();가 포함된 것임
  • 생성자 내에서 가장 상위 라인에 한 번만 존재할 수 있음
  • 한 생성자 안에서 this()와 함께 쓸 수 없음(4번 위배)
Java
class Person {
    String name;

    // 부모 생성자
    Person(String name){
        this.name = name;
    }
}

public class SpiderMan extends Person {
    Spider spider = new Spider();   // 포함 관계(단일 상속 한계 극복)
    boolean isSpider;

    SpiderMan(String name, Spider spider, boolean isSpider) {
        super(name);   // 부모의 생성자 가리킴
        this.spider = spider;
        this.isSpider = isSpider;
    }

    SpiderMan(String name) {
        this(name, new Spider(), true);   // 오버로딩된 자신의 생성자 가리킴
    }

    public static void main(String args[]){
        SpiderMan sm = new SpiderMan("capo");
    }
}