그냥저냥

[개념] 상속이란? 본문

공부/JAVA

[개념] 상속이란?

오양J 2017. 10. 16. 17:47
  1. 상속의 개념

     상속(Inheritance)은 부모(상위) 클래스의 멤버를 자식(하위) 클래스에게 물려주는 것을 의미한다. 이미 구현된 코드를 자식 클래스가 사용할 수 있므로 코드의 중복을 줄여준다.
     하지만 상속을 해도 모든 멤버를 물려주는 것은 아니다. 부모 클래스에서 private 접근 제한을 갖는 필드와 메소드는 상속 대상에서 제외되고 부모 클래스와 자식 클래스가 다른 패키지에 존재하면 default 접근 제한을 갖는 멤버는 상속 대상에서 제외된다.


  2. 클래스 상속

      자식 클래스를 선언할 때 상속할 부모 클래스를 extends 뒤에 기술해주면 된다.

     class People {
    
    	String ssn;
    	String name;
    
    	People(String ssn, String name) {
    		this.ssn = new String(ssn);
    		this.name = new String(name);
    	}
    	String getSSN() {
    		return ssn;
    	}
    	String getName() {
    		return name;
    	}
    }
    
    class Student extends People {
    
    	String studentID;
    
    	Student(String ssn, String name, String studentID) {
    		super(ssn, name);
    		this.studentID = new String(studentID);
    	}
    	String getStudentID() {
    		return studentID;
    	}
    }
    
    public class Demo1 {
    
    	public static void main (String[]args) {
    
                Student tom = new Student("1234", "tom", "5678");
                System.out.println("SSN: "+tom.getSSN());
                System.out.println("Name: "+tom.getName());
                System.out.println("ID: "+tom.getStudentID());
        }
    }<

     Stuent 클래스의 코드에는 stuentID만 있고 이에 해당하는 Getter밖에 없지만 정의되지 않은 SSN, name도 사용 가능하다. 그 이유는 extends를 통해 People 클래스를 상속받아 부모 클래스에 있는 필드와 메소드를 사용할 수 있기 때문이다.

     이처럼 상속으로 중복된 코드를 다시 쓰지 않아도 되므로 코드가 간결해지고 유지보수가 편해진다.

  3. 상위 생성자 호출

     모든 객체가 그렇듯이 생성될 때 생성자 호출이 선행되어야 한다. 그렇다면 상속을 받은 하위 객체가 생성될 때는 어떤 일이 일어날까?
     상속을 받은 하위 객체를 생성할 때에는 상위 생성자가 먼저 호출되고 그 다음에 하위 생성자가 호출된다. 그러면 상위 생성자는 어디에 위치해 있어서 하위 객체가 생성될 때 호출되는 것일까? 답은 하위 생성자에 있다. default로 생성되는 하위 생성자의 코드를 뜯어보면 그 첫번째 줄에 super(); 이라는 코드가 존재한다.
     super()는 상위의 default 생성자를 호출한다. 하지만 매개변수가 있는 생성자를 선언하고 명시적으로 상위 생성자를 호출하면 super(매개값, ..)는 매개값의 타입과 일치하는 상위 생성자를 호출한다. super(매개값, ..)을 생략하고 하위 생성자 코드를 작성하고 돌릴 시에는 컴파일러는 자동으로 super()를 삽입하고 상위 클래스의 default 생성자를 호출한다. 이 경우 상위 클래스에는 default 생성자가 꼭 있어야 한다. super()는 하위 생성자 코드의 맨 첫 번째 줄에 적어야 한다. (이에 대한 예시는 위의 코드를 참고하자)

  4. Overring (매소드의 재정의)

     상속이란 상위 클래스의 멤버를 그대로 하위 클래스에게 물려주는 것이다. 어떤 경우에는 상위 클래스의 메소드가 하위 클래스에게는 적합하지 않을 수 있다. 이런 경우 상위 클래스의 메소드에 대한 수정이 필요할 것이다. 상위 클래스의 메소들 하위 클래스에 적합하도록 수정을 하기 위해 JAVA는 Overring이라는 기능을 도입하였다.
     메소드 오버라이딩의 규칙은 다음과 같다. 
     
     - 부모의 메소드와 동일한 시그니처(리턴 타입, 메소드 이름, 매개 변수 리스트)를 가져야 한다.
     - 접근 제한을 더 강하게 오버라이딩 할 수 없다.
     - 새로운 예외(Exception)를 throws할 수 없다.

     접근 제한을 더 강하게 오버라이딩 할 수 없다는 뜻은 public 접근 제한을 갖는 메소드가 proteced나 private로 접근 제한을 변경 할 수 없다는 뜻이다. 아래의 접근 제한자 그림을 참고하자.
     
                                     
                                                             [그림 1] 접근 제한자

    아래는 위의 예제에서 메소드 getName을 오버라이드한 코드이다. 
    class Student extends People {
    
    	String studentID;
    
    	Student(String ssn, String name, String studentID) {
    		super(ssn, name);
    		this.studentID = new String(studentID);
    	}
      @Override
      String getName() {
        return "Student"+name;
      }
        
    	String getStudentID() {
    		return studentID;
    	}
    }

  5. 부모 메소드 호출 (super)

    오버라이딩을 하는 경우 상위 메소드는 하위 메소드에 가려져 접근이 어렵다. 만약 상위 메소드에 대한 접근이 필요한 경우 우리는 super를 이용하여 접근이 가능하다. 

    public class Ariplane {
      public void land() {
        System.out.println("착륙합니다.");
      }
      public void fly() {
        System.out.printf("일반비행합니다.");
      }
      public void takeoff() {
        System.out.println("이륙합니다.");
      }
    }
    
    public class SupersonicAirplane extends Airplane {
      public static final int NORMAL = 1;
      public static final int SUPERSONIC = 2;
      
      public int flyMode = NORMAL;
      
      @Override
      public void fly() {
        if(flyMode == SUPERSONIC) {
          System.out.println("초음속비행합니다.");
        } else {
          //Airplane 객체의 fly() 메소드 호출
          super.fly();
        }
      }
    }
  6.  final 클래스와 final 메소드

    final 키워드를 붙이면 상속이나 변경을 금지한다는 뜻이다.


Comments