41일차 (1) - java (상속- super, static)

Yohan·2024년 4월 18일
0

코딩기록

목록 보기
57/156
post-custom-banner

super

super 키워드는 상속 받고 있는 부모 객체를 지목할 때 사용하는 키워드

  • super. 을 통해서 부모의 필드나 메서드를 지목할 수 있고, super()를 통해
    부모의 생성자를 호출하는 것이 가능하다.
  • 아래 예시를 통해 super에 대해 더 알아보자!

부모 클래스

package day08.super_;

public class Parent {

    // 필드 : 객체의 속성 - 성질, 데이터, 명사
    int a;
    double b;

    // 생성자 : 객체가 생성될 때 초기화
    Parent() {
        super(); // Object
        System.out.println("Parent 클래스 생성자 호출!");
        this.a = 15;
        this.b = 20.5;
    }

    // 메서드 : 객체의 기능 - 행위, 행동, 동사
    void superMethod() {
        System.out.println("parent a = " + this.a);
        System.out.println("parent b = " + this.b);
    }
}

자식 클래스

package day08.super_;

public class Child extends Parent {

    int a;
    double b;
    boolean c;

    Child() {
        this(100);
        System.out.println("Child 클래스의 생성자 호출!");
        this.c = true;
    }

    Child(int x) {
        super();
        System.out.println("Child 클래스의 2번째 생성자 호출!");
    }

    void childMethod() {
        System.out.println("child a = " + this.a);
        System.out.println("child b = " + this.b);
        System.out.println("child c = " + this.c);
    }
}

main

package day08.super_;

public class Main {

    public static void main(String[] args) {

        Child c = new Child();
//        c.superMethod(); // a = 15, b = 20.5
        c.childMethod(); // a = 0, b = 0.0
    }
}
  1. 자식 클래스에서 생성자 생성시 super()는 자동으로 삽입 (단, this()가 존재한다면 super()가 올 수 없음) -> 부모 클래스의 기본생성자 호출 -> 출력값이 있으면 출력되고 a = 15, b = 20.5로 초기화된다.
  • this()가 들어간 생성자에는 super()가 들어갈 수 없음!
  1. 이렇게 되면 a, b값을 자식이 상속받아서 c.childMethod()를 출력했을 때 a, b값이 15, 20.5로 나올 것 같지만 a = 0, b = 0.0로 출력됨

왜 a = 0, b = 0.0로 출력될까?

  • 상속은 우리의 일반적인 생각처럼 자식이 부모 것을 물려받는 것이 아니기 때문이다.
  • 상속받게되면 자식도 부모에서 초기화한 값으로 초기화 되는 것 같지만 사실은 자식 클래스에 super라는 필드가 생기게 되는 것이다. 즉, 참조받을 수 있게되는 것이지 부모의 값을 직접 물려받는 것이 아님을 알 수 있다.
  • 그림을 통해 확인할 수 있는 점이 하나 더 있다.
    • 자식 객체에서 따로 a,b 필드를 정의해주지 않으면 자식 클래스는 자동으로 자신의 부모에서 a, b 필드를 찾으려고한다. 그래서 필드를 정의하지않으면 super 필드를 통해 부모로 가서 a = 15, b = 20.5를 얻을 수 있다.

사용 제한자 static

정적(static)은 ‘고정된’ 이란 의미를 가지고 있다.

  • static이 붙은 필드는 정적 필드, 메서드는 정적 메서드 라고 칭한다.
  • 참고로 static이 붙지 않은 필드는 인스턴스 필드, 메서드는 인스턴스 메서드 이다.

static 특징

  1. static이 붙게되면 모든 객체가 공유되며 객체 생성없이 접근 가능
    (인스턴스 필드, 메서드는 각 객체별로 따로 관리)
    -> static필드는 선언된 클래스의 이름을 통해 바로 참조할 수 있다.
    객체 생성은 필요 없기 때문에 주소값을 담는 참조 변수도 필요치 않다.
  2. 단순히 선언되는 클래스의 이름만 빌려서 저장 -> 나타낼 주소값이 없음 -> 객체 생성없이 호출이 가능 -> 그래서 this를 가질 수 없다.
package day08.static_;

public class Count {

    // 사용 제한자(usage modifier)
    static int x;   // 정적 필드    : 모든 객체가 공유
    int y;          // 인스턴스 필드 : 각 객체별로 따로 관리

    // 정적 메서드 : 모든 객체가 공유하며 객체 생성없이 접근 가능
    static void m1() {
        System.out.println("static method call!");
        System.out.println("x (static) = " + x);

        // static 메서드 내부에서는 instance필드와 메서드를 직접 참조할 수 없다.
        // static은 객체생성없이 호출되므로 this를 가질 수 없기 때문에

//        System.out.println("y (instance) = " + y);
    }
    // 인스턴스 메서드 : 각 객체별로 따로 실행됨
    void m2() {
        System.out.println("instance method call!");
        System.out.println("x (static) = " + x);
        System.out.println("y (instance) = " + y);
    }
}

  • static 필드, 메서드는 객체 생성 없이 접근 가능
  • 인스턴스 필드, 메서드는 객체 생성 없이는 접근이 불가능
  • 인스턴스 메서드에는 static 변수, 인스턴스 변수 모두 들어갈 수 있다.

static의 메모리 저장법

  • 객체 A, B, C 는 각자 고유한 필드를 하나씩 가지고 있겠지만
    static 변수는 따로 저장되어서 모든 객체가 공유하는 전역 변수로서 동작한다.
    -> static은 값이 누적되지않고 입력한 수로 바뀐다.
Count c1 = new Count();

c1.a += 5;
c1.b += 5;

System.out.println("인스턴스 변수 c1.a: " + c1.a); //5
System.out.println("정적 변수 c1.b: " + c1.b); //5

Count c2 = new Count();
		
c2.a += 7;
c2.b += 7;

System.out.println("인스턴스 변수 c2.a: " + c2.a); //7
System.out.println("정적 변수 c2.b: " + c2.b); //12

Count c3 = new Count();
		
c3.a += 8;
c3.b += 8;

System.out.println("인스턴스 변수 c3.a: " + c3.a); //8
System.out.println("정적 변수 c3.b: " + c3.b); //20

System.out.println("정적 변수 c1.b: " + c1.b); //20
System.out.println("정적 변수 c1.b: " + c2.b); //20

static 초기화 (static 필드 생성자)

  • 정적 초기화자 (static initializer)라고 하며 static필드의 생성자같은 역할
  • static은 따로 초기화 시킬 수 있다. (그냥 생성자에도 들어갈 수는 있음!)
package day08.static_;

public class Person {

    String name;
    int age;
    static String nation; // 국가

    // 정적 초기화자 (static initializer)
    // static필드의 생성자같은 역할 (static필드 초기화담당)
    static {
        nation = "대한민국";
    }

    Person(String name, int age) {
        this.name = name;
        this.age = age;
//        nation = "대한민국"; // this를 가질 수 없기 때문에 그냥 들어감
    }
}

static의 편리함 (import를 통한 생략)

  • 이전에 scanner를 만들었던 코드를 볼 수 있다. scanner 코드는 근본이 static이기 때문에 import를 통해 생략 가능!
  • 이처럼 Math.random() 의 Math도 생략가능하고, 출력할 때 쓰는 System.out.println() 에서 System도 생략 가능!!
        SimpleInput si = new SimpleInput();
        String name = Si.input("이름: ");
        
//         static을 사용하면 객체생성을 안해도 사용가능해서 편리함
//         import static day06.util.SimpleInput.input; 을 불러옴으로써

//         String name = SimpleInput.input("이름: "); 에서 SimpleInput 생략가능
        String name = input("이름: ");
profile
백엔드 개발자
post-custom-banner

0개의 댓글