ToBe끝판왕

[ JAVA ] 상속 본문

■ 프로그래밍 SKILLS/JAVA

[ JAVA ] 상속

업그레이드중 2022. 5. 23. 15:56
반응형

 


 

상속( inheritance )

 

▶  정의

•  부모가 자식에게 물려주는 행위

•  객체지향프로그래밍에서는 부모클래스의 멤버를 자식클래스에게 물려줄 수 있다.

•  상속은 이미 개발된 클래스를 재사용( reuse ) 해서 새로운 클래스를 만들어주므로 코드의 중복을 줄여준다.

•  부모클래스의 수정으로 모든 자식 클래스들도 수정되는 효과를 가져오기 때문에 유지보수 시간을 최소화 한다.

▶  클래스 상속

•  프로그램에서는 자식이 부모를 선택한다.

   자식클래스를 선언할 때, 어떤 부모클래스를 상속받을것인지 결정하고

   부모클래스를 아래와 같이 extends 뒤에 기술한다.

class 자식클래스 extends 부모클래스 {
    //필드
    //생성자
    //메소드
}

•  단, 부모클래스에서 private 접근 제한을 갖는 필드와 메서드는 상속의 대상에서 제외된다.

•  부모클래스와 자식클래스가 다른 패키지에 존재한다면, default 접근제한을 갖는 필드와 메서드도

   상속대상에서 제외된다.

 

▶  상속 예시

•  부모클래스

public class cellPhone {
   // 필드
   String model;
   String color;

   // 생성자

   // 메서드
   void poweron() { System.out.println( "전원을 켭니다." ); }
   void poweroff() { System.out.println( "전원을 끕니다." ); }
   void bell() { System.out.println( "벨이 울립니다." ); }
   void sendVoice( String message ) { System.out.println( "자기 : " + message ); }
   void receiveVoice( String message ) { System.out.println( "상대방 : " + message ); }
   void hangup() { System.out.println( "전화를 끊습니다. " ); }
}
•  자식클래스

public class dmbcellPhone extends cellPhone {
   // 필드
   int channel;

   // 생성자
   void turnOnDmb( String model, String color, int channel) {
      this.model = model;         // cellPhone 에게 받은 필드
      this.color = color;         // cellPhone 에게 받은 필드
      this.channel = channel;
   }

   // 메서드
   void turnOnDmb() {
      System.out.println( "채널" + channel + "번 DMB 방송 수신을 시작합니다." );
   }

   void changeChannelDmb( int channel ) {
      this.channel = channel;
      System.out.println( "채널" + channel + "번으로 바꿉니다." );
   }

   void turnOffDmb() {
      System.out.println( "DMB 방송 수신을 멈춥니다." );
   }
}
•  자식클래스 사용

public class DmbCellPhoneExample {
    public static void main( String[] args ) {
      // DmbCellPhone 객체생성
      DmbCellPhone dmbCellPhone = new DmbCellPhone( "자바폰", "검정", 10 );

      // CellPhone 으로부터 상속받은 필드
      System.out.println( "모델 : " + dmbCellPhone.model );
      System.out.println( "색상 : " + dmbCellPhone.color );

      // DmbCellPhone의 필드
      System.out.println( "채널 : " + dmbCellPhoe.channel );

      // CellPhone으로부터 상속받은 메서드 호출
      dmbCellPhone.powerOn();
      dmbCellPhone.bell();
      dmbCellPhone.sendVoice( "여보세요" );
      dmbCellPhone.receiveVoice( "안녕하세요!" );
      dmbCellPhone.sendVoice( "반갑습니다." );
      dmbCellPhone.hangUp();

      // DmbCellPhone의 메서드 호출
      dmbCellPhone.turnOnDmb();
      dmbCellPhone.changeChannelDmb( 12 );
      dmbCellPhone.turnOffDmb();
   }
}

 

 

 

▶  부모생성자 호출

•  자식 객체를 생성하면, 부모객체가 먼저 생성되고 자식객체가 그 다음 생성된다.

•  모든 객체는 클래스의 생성자를 호출해야만 생성된다. ( 부모 객체도 예외 X )

•  부모 생성자는 자식 생성자의 맨 첫줄에서 호출된다.

public DmbCellPhone() {
    super();                   // 부모의 기본 생성자를 호출
}

만약, 직접 자식생성자를 선언하고 명시적으로 부모 생성자를 호출하고 싶다면

자식클래스( 매개변수 선언, ... ) {
     super( 매개값, ... );    // 매개값의 타입과 일치하는 부모 생성자 호출
}

 

 

▶  부모생성자 호출 예시

•  부모 클래스

public class People {
   public String name;
   public String ssn;

   // 부모클래스 생성자 명시( 기본 생성자 X )
   public People( String name, String ssn ) {
       this.name = name;
       this.ssn = ssn;
   }
}
•  자식 클래스

public class Student extends People {
    public int studentNo;

    public Student( String name, String ssn, int studentNo ) {
        super( name, ssn );      // 부모생성자 호출
        this.studentNo = studentNo;
    }
}

// Student 클래스 생성자는 name, ssn, studentNo를 매개값으로 받아서
// name, ssn은 부모생성자를 호출하기 위해 매개값으로 넘겨준다.
•  자식 객체 사용

public class StudentExample {
    public static void main( String[] args ) {
      Student student = new Student( "홍길동", "123456-1234567", 1 );
      System.out.println( "name : " + student.name ); // 부모에게 물려받은 필드 출력
      System.out.println( "ssn : " + student.ssn );   // 부모에게 물려받은 필드 출력
      System.out.println( "studentNo : " + student.studentNo );
    }
}

 

 

 

 

▶  메서드 재정의( Overriding )

•  부모클래스의 메서드를 자식클래스에서 사용하기 부적합한 경우 자식클래스에서 부모클래스의

   메서드를 재정의 하는것 ( = 오버라이딩 )

 

•  메서드 재정의 규칙

   -  부모의 메서드와 동일한 리턴타입, 메서드이름, 매개변수 목록 을 가져야 한다.

   -  접근 제한을 더 강하게 재정의 할 수 없다.\

ex) 부모메서드가 public인 경우 , 자식메서드는 default나 private 접근제한을 사용할 수 없다.

 

•  메서드가 재정의되면 부모 객체의 메서드는 숨겨지기 때문에, 자식 객체에서 메서드를 호출하면

   재정의된 자식 메서드가 호출된다.

 

•  보통 메서드 재정의 할때는 @override 어노테이션을 사용한다.

 

 

▶  메서드 재정의 예시

 
•  부모클래스

public class calculator {
    // 메서드
    double areaCircle( double r ) {
       System.out.println( "Calculator 객체의 areaCircle() 실행" );
           return 3.14159 * r * r;
    }
}
•  자식클래스

public class Computer extends Calculator {
     @override    // 메서드 재정의
     double areaCircle( double r ) {
        System.out.println( "Couputer 객체의 areaCircle() 실행" );
           return Math.PI * r * r;
     }
}
•  오버라이딩( Overriding )

public class ComputerExample {
    public static void main( String[] args ) {
       int r = 10;

       Calculator calculator = new Calculator();  // 부모객체 생성
       System.out.println( "원 면적 : " + calculator.areaCircle(r) );
       System.our.println();

       Computer computer = new Computer(0;        // 자식객체 생성
       // 재정의 메서드 호출
       System.out.println( "원 면적 : " + computer.areaCircle(r) ); 
    }
}

 

 

 

▶  부모 메서드 호출

•  자식클래스 내부에서 오버라이딩된 부모클래스의 메서드를 호출해야하는 경우 명시적으로

   super 키워드를 붙여서 부모메서드를 호출 할 수 있다.

•  부모 메서드 호출

super.부모메서드();

 

 

▶  final 클래스 & final 메서드

•  final .키워드는 클래스, 필드, 메서드를 선언할 때 사용할수 있는데 해당 선언이 최종상태이고

   더이상 수정될 수 없음을 의미한다.

•  클래스를 선언할 때, final 키워드를 class앞에 붙이면 클래스는 최종적인 클래스이므로 상속할 수 없는 클래스가 된다.

•  메서드를 선언할 때, final 키워드를 붙이면 메서드는 최정족언 메서드이므로 재정의 할 수 없는 메서드가 된다.

 
•  final 클래스

public final class String { ... }

=> final 클래스는 부모클래스가 될 수 없어 자식클래스를 만들수 X
•  final 메서드

public final 리턴타입 메서드( [매개변수, ... ] ) { ... }

=> 부모클래스에서 선언된 final 메서드는 자식클래스에서 재정의 X

 

 

 

 

반응형
Comments