수업/정리

220106 Inheritance, Method Overriding, Abstract Class

jumphare 2022. 1. 6. 18:35

어제에 이어서

객체지향프로그래밍

***상속Inheritance***
자식(하위, 파생, sub) 클래스가 부모(상위, super) 클래스의 멤버를 물려받는 것
상속 대상-> 부모의 필드, 메소드 (생성자는 받을 수 없음)
-> 물려받는다= 부모클래스에서 상속받은 멤버는 따로 선언하거나 불러올 것 없이 내것처럼 바로 쓸 수 있다
하위에서 상위 클래스를 선택해 상속받을 수 있다
하위클래스는 상위클래스에서 받은 멤버와 하위클래스에서 추가한 멤버를 모두 사용할 수 있음
-> 상위클래스의 필드1 메소드1을 받고 자신이 가진 필드2 메소드2 까지 다 사용 가능하다는 것
!단, 생성자는 상속받을 수 없으니 주의합시다!
+) 부모클래스는 자식클래스의 멤버를 가져다 사용할 수 없음!


상속 많이 활용하는 곳
1. API - GUI 다룰 때 많이 사용함
ex) java.awt , javax.swing , javafx 등
2. JSP(Model2)

* 상속의 효과
- 부모 클래스 멤버를 재사용 -> 빠른 개발 가능
- 코드 중복 줄임
유지, 보수 편리
- 객체 다형성

extends
: 자식 클래스가 상속할 부모 클래스를 지정하는 키워드
부모 클래스: class A {
자식 클래스: class B {
상속 시 class B extends A {
(단, 자바는 단일 상속이므로 부모클래스 나열 불가 -> 딱 하나만 가능!)
class C extends A, B { <- 다중 상속 불가능

//사용되는 경우가 어느정도 정해져있음
ex. FrameTest.java , FrameTestEx.java 파일 참고

Frame 클래스 안에는 setSize 메소드가 존재하지 않음 -> 부모클래스인 java.awt.Window에 있는 메소드임 -> 상속받아 사용중
ex. SuperSub00.java 파일 참고
2차원 (x,y) 좌표와 3차원 (x,y,z) 좌표를 받는 두 클래스가 있다고 할 때, x,y가 서로 겹치므로! 3차원 좌표를 받는 클래스가
x,y 필드-> 2차원 좌표를 받는 클래스로부터 상속받아 사용
z 필드-> 3차원 좌표 받는 클래스 자신의 필드를 사용
이렇게 이용하는 게 효율적임 (재사용 가능, 중복 줄임, 유지보수 편리)

오버라이딩Overriding
부모 클래스로부터 상속받은 멤버를 자식 클래스에서 재정의해서 사용하는 것
-> 자식 클래스에서 멤버를 재정의하는 경우 재정의된 멤버는 자식클래스에 소속됨

1. 필드

위 캡처에서 10의 값을 가진 x는 부모클래스에 있지만 40으로 재정의된 x는 자식클래스에 소속됨
이때 부모클래스의 x = 은닉변수(쉐도우 변수) // 기존 값이 재정의되며 뒤로 숨어버렸기 때문

이후 자식클래스에서는 재정의한 필드만 사용 가능하지만, 이게 부모클래스의 값까지 바뀌어버린 건 아니기 때문에
부모클래스의 필드값을 가져오고 싶다고 하면?
-> super: 부모 클래스를 의미하는 레퍼런스 변수
int num= super.x;   //이렇게 super클래스의 x라고 명시해주면 부모클래스 값이 오게 된다
-> 자식 클래스의 메소드 안에서만 사용해야 함 (자식의 특정 메소드 내에서만 사용 가능하도록)

* this. 와 super. 의 차이

this.      : 생성자와 메소드에서 매개변수와 멤버변수 이름이 동일한 경우에 사용
this()   : 같은 클래스내에 있는 다른 생성자를 호출

super.   : 부모 클래스에 있는 은닉된 멤버변수와 메소드를 호출할 때 사용
super() : 부모 클래스의 매개변수를 가진 생성자를 호출 할 때 사용


2. 메소드 오버라이딩Method Overriding 
: 슈퍼클래스에 있는 메소드를 서브클래스가 오버라이딩하면, 서브클래스로 선언된 객체는 슈퍼클래스의 메소드를 상속받지 못함(은닉 메소드가 되었기 때문)

- 즉 main에서 서브클래스로 객체 생성 시
Chile c=new Child(); -> 서브클래스에서 메소드오버라이딩된 메소드만 호출 가능

- 만약 슈퍼클래스의 은닉메소드를 가져오고 싶다면 슈퍼클래스로 객체 따로 생성해줘야함
Parent p=new Parent(); -> 메인에 슈퍼클래스(자기자신)의 메소드를 호출할 수 있음
   아니면 자식클래스 메소드 안에서 super.메소드명 형식으로 호출하거나.
super.parentPrn(); -> 자식클래스의 특정 메소드 안에 한정해 은닉메소드 불러올 수 있음

* 생성자
1. 생성자는 기본적으로 상속이 되지 않는다
2. 자식클래스를 이용해서 객체를 생성할때 자식클래스의 생성자(기본생성자,매개변수 있는 생성자 모두 가능)가 호출되면, 부모클래스의 기본생성자가 자동으로 호출된다
이때, 부모클래스 생성자 먼저 호출-> 다음으로 자식클래스 생성자 호출

3. 매개변수가 있는 생성자가 있는 경우에는 더이상 컴파일러가 기본 생성자를 자동으로 생성해 주지 않는다

    -> 부모 클래스에서 매개변수 있는 생성자와 기본 생성자 둘다 쓸거면 기본생성자 따로 만들어줘야 함!

         ↓ 4번 참고


4. super()
- 부모 클래스의 매개변수가 있는 생성자를 자식 클래스에서 호출 할 때 사용 (명시적 호출)
자식 클래스의 생성자 첫번째 줄에 넣어야 사용 가
super()로 부모클래스 생성자를 호출하면 기본 생성자는 호출하지 않음
    -> 부모 클래스에 매개변수가 있는 생성자만 존재하는 경우 필요함
    -> 부모 클래스의 기본 생성자가 필요한 경우, 매개변수 있는 생성자가 있을땐 자동으로 생성되지 않으니 직접 만들어서 호출을 하든 해야 함

부모 클래스에 기본 메소드가 없는데 자식 클래스 생성자 호출하면 이렇게 오류 발생함


제한
- 부모 클래스의 private 접근제어자 갖는 필드, 메소드 제외
- 부모 클래스가 다른 패키지에 존재할 경우 default 접근제어자 갖는 필드, 메소드 제외

      ↓ 표 참고
접근제어자

1. 상속 관계가 있을 때
   2개의 클래스(부모,자식 클래스)가 같은 패키지 안에 들어 있으면, 
   부모의 접근제어자가 default, protected, public 일 때 자식클래스에서 접근 가능
   (private접근 제어자는 자식 클래스라도 접근 할 수 없음)

2. 상속 관계가 있을 때
   2개의 클래스(부모,자식 클래스)가 다른 패키지 안에 들어 있으면,
   부모의 접근제어자가 protected, public 일 때 자식클래스에서 접근 가능

3. 상속 관계가 없을 때
   2개의 클래스가 서로 다른 패키지 안에 들어 있으면
   public 만 다른 클래스에서 접근 가능

코드를 보면 알겠지만 protected 접근제어자는 상속관계가 있는 부모 클래스가 다른 패키지에 있을 때 그 필드에 접근할 수 있음. 상속관계 없다면 다른 패키지일 때 public만 불러오기 가능! 차이 기억해두자

*final
final+ 멤버변수 -> 상수 (값 수정 불가)
final+ 메소드 -> 메소드 오버라이딩 불가
final+ 클래스 -> 상속 불가

*static
 ->정적 메소드는 메소드 오버라이딩 불가능
(+)
this. 레퍼런스 변수 사용 불가
정적멤버변수만 사용 가능


***추상 클래스 Abstract Class***
: 실체 클래스들의 공통되는 필드와 메소드를 정의한 클래스로, 실체(구현) 클래스의 부모 클래스 역할
(실체(구현) 클래스: 객체를 만들어 사용할 수 있는 클래스) --> 추상 클래스는 자체적으로 객체를 만들 수 없음
ex) 새, 물고기, 곤충 (실체) -> 동물 (추상)

abstract class AbsClass{ //abstract 붙은게 추상 클래스
}

* 추상 클래스 용도
- 실체 클래스의 공통된 필드, 메소드명 통일하려는 목적
- 실체 클래스 작성 시 시간 절약 -> 추가적인 필드, 메소드만 선언하면 되니까
- 설계 규격 만들때 -> 실체 클래스가 가져야할 필드, 메소드를 추상클래스에 미리 정의하고 추상클래스를 상속받아 작성함
 
구성요소
추상 메소드, 일반 메소드, 멤버변수
(추상메소드: 메소드명만 있고 내용은 가지고 있지 않은 메소드)

   abstract class AbsClass{
       int a=10;                                  //멤버변수
       void Method02(){                    //일반 메소드 -> {} 있음
       abstract void Method01();          //추상메소드 -> {} 없음 = 내용 없음
       abstract int Method03(int a);
      //추상메소드도 매개변수 있고 자료형 지정할수 있음.
      //하지만 내용 없는 건 똑같고, int형 메소드를 만들면 메소드 오버라이딩 시 return 반드시 해야함 당연함
       }
   }
+) 생성자를 만들수는 있지만, 추상 클래스는 자체적으로 객체를 생성할 수 없어서 만들어도 사용하지 않음!
    보통 자식클래스가 객체 생성하면 부모클래스의 기본생성자를 호출할 수 있고 추상클래스도 똑같음
    하지만 사용하지 않음! 추상클래스는 사용하는 목적이 명확해서, 그 용도로만 사용함
    생성자를 호출해서 사용할거라면 굳이? 추상클래스를 사용할 필요가 없기 때문에... 안 쓴다고 생각하면 됨


일반 클래스가 extends로 추상 클래스를 상속받으면 반드시 추상메소드를 오버라이딩해야함
 -> 메소드명만 있고 내용이 없으니까, 자식클래스가 내용을 정의해서 구현해줘야 함
       그리고 애초에 이걸 쓰려고 추상클래스를 상속받은 거니까 꼭 오버라이딩해야지

+) 추상클래스도 단일 상속만 가능 (java는 다중상속 허용하지 않음 추상클래스도 예외 없음)

추상클래스 만드는 법



면접에서 기본적인 단어를 물어보니까 바로 설명할 수 있도록 개념 문장, 키워드로 확실히 외워두는게 좋다