ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 상속(Inheritance), @Override, super
    JAVA/개념 - 김영한 강의 2024. 9. 27. 18:34

     

    상속

    • 기존 클래스의 속성과 메서드를 새로운 클래스가 물려받아 사용할 수 있게 함
    • (자식클래스명) extends (부모클래스명)
      • 부모 클래스: 상속을 통해 자신의 필드와 메서드를 다른 클래스에 제공하는 클래스
      • 자식 클래스: 부모 클래스로부터 필드와 메서드를 상속받는 클래스
    • 단 하나의 부모클래스만 상속받을 수 있다
    • 자식은 부모클래스에 접근할 수 있지만, 부모는 자식 클래스에 접근할 수 없다.(= 자식은 부모로부터 유산을 상속받지만 
    // 부모 클래스
    class Animal {
    	void sound() {
        	System.out.println("동물이 소리를 냅니다.");
            }
    }
    
    // 자식 클래스
    class Dog extends Animal {
     	// 부모클래스의 메서드를 재정의(오버라이딩)
        @Override
        void sound() {
        	System.out.println("강아지가 멍멍 소리를 냅니다.");
            }
        }
        
    public class Main {
    	public static void main(String[] args) {
        
        	Animal animal = new Animal();
            Dog dog = new Dog();
            
            animal.sound();
            dog.sound();
            }
    }

     

     

     

    상속 메모리 구조

    ElectricCar electricCar = new ElectricCar();

     

    • 상속 받게 되면 부모 클래스도 함께 인스턴스가 생성된다(즉 자식, 부모 모두 생성)
    • 상속 관계의 객체를 호출할 때, 대상 타입을 정해야 한다. 
    • 현재 타입에서 기능을 찾지 못하면 상위 부모 타입으로 기능을 찾아서 실행한다. 

     

     

    @Override

    : 상위 클래스의 메서드를 오버라이드하는 것

     

     

    Overriding 조건

    • 메서드 이름이 같아야 한다.
    • 매개변수(파라미터), 타입, 순서, 개수가 같아야 한다.
    • 반환타입이 같아야 한다.
    • 오버라이딩 메서드의 접근제어자는 상위 클래스의 메서드보다 더 제한적이어서는 안된다. 
    • static, final, private 키워드가 붙은 메서드는 오버라이딩 될 수 없다.
    • 생성자는 오버라이딩 할 수 없다.

     

    Overloading VS Overriding

    • 오버로딩(Overloading): 메서드 이름이 같고 매개변수(파라미터)가 다른 메서드를 여러개 정의하는 것을 메서드 오버로딩(Overloading)이라고 한다. 과하게, 넘치게 담았다는 것인데 같은 이름의 메서드를 여러개 정의했다는 뜻이다.
    • 오버라이딩(Overriding): 하위 클래스에서 상위 클래스의 메서드를 재정의하는 과정을 의미한다. 따라서 상속 관계에서 사용한다. 부모의 기능을 자식이 다시 정의하는 것이다. over+ride 자식의 새로운 기능이 부모의 기존 기능을 넘어 타서 새로운 기능으로 덮어버린다고 생각하면 된다. 오버라이딩은 다른말로 '재정의'라고 한다.

     

     

    super - 부모 참조

    부모와 자식의 필드명이 같거나 메서드가 오버라이딩 되어 있으면, 자식에서 부모의 필드나 메서드를 호출할 수 없다. 
    이때 super 키워드를 사용하면 부모를 참조할 수 있다. super 는 이름 그대로 부모 클래스에 대한 참조를 나타낸다.

    package extends1.super1;
    
    public class Parent {
    	public String value = "parent";
        
        public void hello() {
     		System.out.println("Parent.hello");   
        }
    }
    package extends1.super1;
    
    public class Child extends Parent {
    	public String value = "child";
        
        @Override
        public void hello() {
        	System.out.println("Child.hello");
        }
        
        public void call() {
        	System.out.println("this value = " + this.value); //this 생략 가능
            System.out.println("super value = " +super.value);
            
            this.hello(); // this 생략 가능
            super.hello();
            }
        }
    package extends1.super1;
    
    public class Super1Main {
     	public static void main(String[] args) {
     	
        Child child = new Child();
     	child.call();
     	}
    }

     

     

     

     

    super - 생성자

    상속 관계의 인스턴스를 생성하면 결국 메모리 내부에는 자식과 부모 클래스가 각각 다 만들어진다. child를 만들면 부모인 Parent까지 함께 만들어지는 것이다. 따라서 각각의 생성자도 모두 호출되어야 한다.

     

    상속 관계를 사용하면 자식 클래스의 생성자에서 부모 클래스의 생성자를 반드시 호출해야 한다.(규칙)
    상속 관계에서 부모의 생성자를 호출할 때는 super(...) 를 사용하면 된다

     

    package extends1.super2;
    	public class ClassA {  // 부모클래스
     		public ClassA() {
     		System.out.println("ClassA 생성자");
     	}
    }
    package extends1.super2;
    
    public class ClassB extends ClassA {
    
    	// public classB() {} ClassB의 기본생성자는 생략. 왜? 밑에 생성자가 있으니까. 
    
    	public ClassB(int a) {
        	super(); // 부모클래스의 기본 생성자 생략 가능
            System.out.println("classB 생성자 a="+a);
            }
            
            public ClassB(int a, int b) {
            	super();  // 기본 생성자 생략 가능. 여기서 알수있는건 부모 생성자는 반드시 호출되어야 한다.
                System.out.println("ClassB 생성자 a=" +a +" b="+b);
            }    
       }
    • ClassB 는 ClassA 를 상속 받았다. 상속을 받으면 생성자의 첫줄에 super(...) 를 사용해서 부모 클래스의 생성자를 호출해야 한다.
    • 예외로 생성자 첫줄에 this(...) 를 사용할 수는 있다. 하지만 super(...) 는 자식의 생성자 안에서 언젠가는 반드시 호출해야 한다.
    • 부모 클래스의 생성자가 기본 생성자(파라미터가 없는 생성자)인 경우에는 super() 를 생략할 수 있다.
    • 상속 관계에서 첫줄에 super(...) 를 생략하면 자바는 부모의 기본 생성자를 호출하는 super() 를 자동으로 만들어준다.

     

     

     

    package extends1.super2;
    	public class ClassC extends ClassB {
     		public ClassC() {
     		super(10, 20);
    	 	System.out.println("ClassC 생성자");
     	}
    }
    • ClassC는 ClassB를 상속 받았다. ClassB에는 두 가지 생성자가 있다. 
      • ClassB(int a)
      • ClassB(int a, int b)
    • 생성자는 하나만 호출할 수 있다. 두 생성자 중에 하나를 선택하면 된다. ClassC에 super(10, 20)가 있는 것을 보아 후자의 생성자를 택했음을 알 수 있다.
    • ClassC의 부모인 ClassB에는 기본 생성자가 없다. 따라서 부모의 기본 생성자를 호출하는 super()를 사용하거나 생략할 수 없다.  

     

    package extends1.super2;
    
    public class Super2Main {
     	public static void main(String[] args) {
     	ClassC classC = new ClassC();
        }
    }

     

    실행결과:

     

    ClassA 생성자
    ClassB 생성자 a=10 b=20
    ClassC 생성자

     

    참고로 ClassA -> ClassB -> ClassC 순서로 실행된다. 왜냐하면 자식 생성자의 첫 줄에서 부모의 생성자를 호출해야 하기 때문이다.

    댓글

Designed by Tistory.