ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Camel][Java] Java에서의 상속(Inheritance)이란? (feat. super 키워드)
    Java/개념 정리 2020. 2. 19. 20:46

    상속(Inheritance)이란?

    상속이란 객체지향 프로그래밍에서 굉장히 중요한 부분입니다. 대부분의 처음 Java를 공부하는 사람은 상속을 재활용의 목적으로 이해하는 경우가 많습니다. 하지만 Java에서 상속이 지니는 의미는 재활용 그 이상이라고 할 수 있습니다. 

     

    결론부터 말하자면 상속은 기존의 클래스를 재활용해 새로운 클래스를 작성하기위한 수단입니다. 우리는 상속을 통해 연관성이 있는 일련의 클래스에 대한 공통의 규칙을 정할 수 있습니다. 

     

    상속은 기존에 정의된 클래스에 메소드와 변수를 추가해 새로운 클래스를 정의하는 것입니다. 즉 재활용+@ 라고 할 수 있는 것입니다. 상속을 사용하기 위해서는 우리는 앞으로 extends라는 키워드를 사용할 것입니다. 

     

    class Animal {
    	private String kind;
        	public void printKind(){
        		System.out.println("Kind is "+kind);
        	}
    }
    class Camel extends Animal {
    	private String name;
        	private String area;
            public Camel(String kind, String name, String area) {
            	super(name);
                	this.name = name;
                	this.area = area;
            }
        	public void printName() {
        		System.out.println("name is "+name);
         	  	System.out.println("It is active at the" + area);
          	  	printKind();  // Animal 클래스를 상속했기 때문에 사용가능하다.
       	}
    }

    위의 코드를 확인해보면 Camel 클래스에서 선언하지 않은 printKind 메소드를 사용한 것을 확인할 수 있습니다. Camel 클래스에서 Animal 클래스를 상속했기 때문입니다.

     이처럼 Camel 클래스에서 Animal 클래스를 상속할 때 우리는 두 클래스가 상속관계에 있다고 말합니다. 상속을 받는 클래스를 하위클래스, 유도클래스, 자식클래스라고도 하며, 상속의 대상이 된 클래스는 상위클래스, 기초클래스, 부모클래스라고 합니다. 즉, Camel 클래스는 하위클래스이며 Animal클래스는 상위클래스인 것입니다. 

     

    super 키워드의 의미

     위 코드의 Camel 클래스의 생성자의 내부를 확인해보면 super(name)이라는 코드를 확인할 수 있습니다. 이 코드의 의미는 상위 클래스의 생성자를 호출하되 name을 인자로 전달하라는 것입니다. 

     하위 클래스인 Camel 클래스의 생성자가 호출되고, super 키워드에 의해 상위 클래스인 Animal 클래스의 생성자가 호출되고 먼저 실행되게 됩니다. 하위클래스의 생성자가 먼저 호출 됬지만 나중에 호출된 상위 클래스의 생성자가 먼저 실행되면서 상위 클래스의 멤버가 먼저 초기화되는 것입니다. 하위 클래스의 생성자의 실행은 그 이후에 이루어지게 됩니다. 

     만약 상위클래스의 멤버에 대한 초기화가 상위클래스의 생성자를 통해 초기화되지 않으면, 상위 클래스를 상속하는 모든 하위 클래스가 상위클래스의 모든 인스턴스 변수를 초기화해야하는 매우 부담스러운 상황이 발생하게 됩니다. 그렇기 때문에 상위 클래스의 인스턴스 변수는 상위 클래스의 생성자 내에서 초기화가 되어야 하는 것입니다. 이를 위해서 하위 클래스에서는 상위 클래스의 인스턴스 변수를 초기화하기 위해 필요한 데이터를 super 키워드를 사용해 전달하게 됩니다. 

     하위 클래스의 생성자가 상위 클래스의 생성자를 호출할 수 없는 구조로 이루어져 있다면 하위 클래스의 인스턴스는 생성이 불가능한 것입니다. 그런데 여기서 다음과 같은 의문을 가지는 사람이 있을 수 있습니다. 

     

    "위 코드에서 상위 클래스의 생성자가 정의되어 있지 않은데요?" 

     

    위의 코드와 같이 두 클래스가 정의되면 상위 클래스인 Animal 클래스에서 Animal() { } 과 같은 Default 생성자가 자동으로 삽입됩니다. 만약 하위 생성자에서 직접 상위 생성자의 호출을 하지 않더라도 Java는 자동으로 상위 클래스의 Default 생성자를 호출합니다. 

     

    그렇다면 위의 코드에서 잘못된 점을 발견했습니까? 네. 그렇습니다. 위 코드에서 하위 클래스의 생성자 내부에 있는 super(name)은 Default 생성자가 아니므로 컴파일이 되지 않습니다. 그렇기 때문에 아래와 같이 코드를 수정해주면 정상적으로 컴파일되는 것을 확인 할 수 있습니다. 

    class Animal {
    	private String kind;
        	public Animal (String kind) {           // 하위 클래스의 생성자에서 호출하는 상위 클래스의
            	this.kind = kind;		// 생성자가 Default가 아니므로 이처럼 생성자를 선언해준다.
            }
        	public void printKind(){
        		System.out.println("Kind is "+kind);
        	}
    }
    class Camel extends Animal {
    	private String name;
        	private String area;
            public Camel(String kind, String name, String area) {
            	super(name);
                	this.name = name;
                	this.area = area;
            }
        	public void printName() {
        		System.out.println("name is "+name);
         	  	System.out.println("It is active at the" + area);
          	  	printKind();  // Animal 클래스를 상속했기 때문에 사용가능하다.
       	}
    }

     

    final 클래스, final 메소드

    우리가 일반적으로 final 키워드를 생각하면 생각나는 것은 상수화입니다. 하지만 이 final 키워드는 클래스를 정의할 때도 사용할 수 있으며 메소드의 선언에도 사용할 수 있습니다. 

    final class Camel() { . . . }
    
    class Animal () {
    	final void showNameOfAnimal() { . . . }
    }

     클래스의 정의에서 final 키워드를 사용하면 상속을 허용하지 않는 클래스를 정의하는 것이 됩니다. 이러한 클래스의 대표적인 사례로는 String 클래스가 있습니다. 

     그렇다면 메소드의 선언에 final 키워드를 사용하면 어떻게 될까? 위의 코드처럼 Animal 클래스의 메소드가 final로 선언되면 final로 선언된 메소드의 오버라이딩을 허용하지 않는다는 것입니다. 이르한 구조를 확인할 수 있는 메소드는 Object 클래스의 wait(), notify()와 같은 클래스들이 있습니다.

     

     

    다음 포스팅에선 상속과 관련된 접근제어 지시자에 대해 포스팅하도록 하겠습니다.

     

     

    댓글

Camel`s Tistory.