언어 공부 내용 정리/Java

객지프 기말대비 정리 (5장)

wosrn 2023. 7. 15. 23:29

다시 풀어보기 : (x,y)의 한 점을 표현하는 point 클래스 구현(생성자 없이, x/y는 private)하고 이를 상속받아 색을 추가한 colorpoint 클래스 구현(역시 생성자 없고 color은 private) ->이를 활용하는 pointex 클래스 구현(실행 메소드 있는 클래스 -> point객체랑 colorpoint객체 하나씩 만들어서 점이랑 색 출력
+ppt기준 5-2,5-3

 

<5장 : 상속>

  • 상속 : 부모클래스의 필드,메소드를 자식클래스가 물려받음
  • 부모 클래스 = 슈퍼 클래스 / extends 키워드 사용
  • 다중상속 지원 x (부모 하나에 자식 여러명은 되지만 자식 하나에 부모가 여럿인건 안됨)
  • 생성자는 상속 대상에서 제외됨

 
 

  • 서브클래스는 서브클래스 멤버와 슈퍼클래스 멤버 모두를 갖고있다 ! 슈퍼클래스 멤버가 private 인 경우 getter,setter로 접근 가능(private이라고 해서 getter와 setter가 다 있어야 하는건 아니고 필요에 따라 코드짜면 됨)
위 예제 생성자(+super() 사용) 있는 버전
  • 슈퍼클래스의 private 멤버를 getter setter뿐만 아니라 생성자 메소드로도 접근 가능함

 
<접근 지정자>

  • 슈퍼클래스의 private 멤버 : 자식클래스에서 직접 접근 불가능 , getter setter 혹은 메소드에서만 접근 가능
  • 슈퍼클래스의 default 멤버 : 동일 패키지 내에서만 접근 가능
  • 슈퍼클래스의 protected 멤버 : 동일패키지 혹은 다른 패키지의 상속클래스에서 접근 가능 
  • 슈퍼클래스의 public 멤버 : 다른 모든 클래스에서 접근 가능

<서브 클래스/슈퍼 클래스의 생성자 호출 및 실행>

  • 서브클래스의 객체가 생성될 때 : 서브클래스의 생성자와 슈퍼클래스의 생성자가 모두 실행됨
  • 호출 및 실행 순서 : 서브클래스 생성자 호출 - 슈퍼클래스 생성자 호출 - 슈퍼클래스 생성자 실행 - 서브클래스 생성자 실행
  • 서브클래스에서 슈퍼클래스의 생성자 선택 : 서브클래스 생성자에서 슈퍼클래스 생성자를 선택할 수 있고, 선택하지 않는 경우 자동으로 슈퍼클래스의 기본생성자 선택(서브클래스의 생성자가 매개변수 있든 없든) / 선택방법 : super() 이용
  • 슈퍼클래스에 기본생성자 없는 경우 위의 이유로 에러 발생
  • super() : super(인자) 형태로 서브클래스 생성자에서 슈퍼클래스의 생성자 지정호출 / 단 반드시 서브클래스 생성자 코드의 제일 첫 라인에 와야함(this() 생성자와 동일) / 사용방식은 this() 와 유사함

 
 
<업캐스팅> : 서브클래스 객체를 슈퍼클래스 타입으로 타입 변환  -> 자동변환

  • 객체는 여전히 서브클래스인데 타입(시야)을 슈퍼클래스로 바꾸는거 ! (슈퍼클래스의 레퍼런스가 서브클래스를 가리키도록 치환)
  • 서브클래스의 객체는 슈퍼클래스의 멤버를 모두 가지고 있고 슈퍼클래스의 객체로 취급 가능 (사람은 생물이다)
class Person { … }
class Student extends Person { … }

Student s = new Student();
Person p = s; // 업캐스팅, 자동타입변환

서브클래스 타입 객체를 슈퍼클래스 타입 객체에 치환하는 식
슈퍼클래스 타입 레퍼런스 p가 서브클래스 객체를 가리키도록 치환됨

  • 업캐스팅된 레퍼런스 : 객체 내에 슈퍼클래스의 멤버만 접근 가능함
  • 업캐스팅된 서브클래스 객체는 자신의 고유한 속성을 잃어버리는게 아니고 여전히 갖고있는데 잠시 가려진 것

 
<다운캐스팅> : 슈퍼클래스 객체를 서브클래스 타입으로 변환 -> 명시적 타입변환 필요 !

//위 코드를 다시 다운캐스팅 하는 코드

student s = (student)p ;

서브클래스 객체가 슈퍼클래스 타입으로 업캐스팅 되었다가 , 슈퍼클래스 타입의 서브클래스 객체가 다시 서브클래스 타입으로 다운캐스팅된 예제
= 서브클래스 타입 레퍼런스 s는 p가 가리키던 student 객체를 다시 가리키게 됨
= 서브클래스 객체를 가리키는 레퍼런스 타입이 변화되는거 (서브 ->슈퍼> 다시 서브)

class Person { … }
class Student extends Person { … }
...
Person p = new Student("이재문"); // 업캐스팅 : student를 person에 넣는거니까 자동변환
…
Student s = (Student)p; // 다운캐스팅, (Student)의 타입 변환 표시 필요 . 서브 객체에 슈퍼 객체를 타입변환하여 대입

 

  • instanceof 연산자와 객체의 타입 판단 : 업캐스팅된 레퍼런스로 객체의 타입 판단 어려움
//슈퍼클래스 person, 자식1클래스 student, 자식2클래스 professor


person p = new person();
person p = new student();
person p = new professor();

person타입의 레퍼런스 변수 p는 person,student,professor 객체 모두를 가리킬 수 있어서 실행 중 p가 가리키는 객체의 실제 클래스 타입(실체)가 뭔지 구별할 필요가 있음 => instanceof !

  • 객체레퍼런스 instanceof 클래스 타입     =>  ''레퍼런스"가 가리키는 객체가 해당 클래스 타입이면 true,아니면 false 반환
  • 이때 실제 객체 클래스를 포함한 객체 클래스의 부모클래스는 클래스 타입으로 가능
  • instanceof는 클래스에만 적용됨 -> 기본형 변수엔 사용 불가, string엔 사용 가능(클래스니까)

 
 
<오버라이딩>

  • 슈퍼클래스 메소드를 서브클래스에서 재정의
  • 메소드 이름,매개변수,리턴타입은 그대로 유지하고 코드 바디만 수정
  • 동적 바인딩 발생 : 실행할 메소드를 실행 시에 결정하는것, 오버라이딩 메소드가 항상 호출된다
  • super 키워드  : super은 슈퍼클래스의 멤버 접근 시에 사용되는 레퍼런스 / 서브클래스에서만 사용/ 슈퍼클래스의 메소드를 호출 / 컴파일러는 super의 접근을 정적 바인딩으로 처리 => super. 으로 접근가능
  •  

서브클래스 객체를 슈퍼클래스 타입으로 정의 (업캐스팅) , 슈퍼클래스의 시선에서 보더라도 객체의 실체는 서브클래스이기 때문에 오버라이딩된 서브클래스의 메소드가 호출됨 = 동적 바인딩 !

super 키워드 사용 예시 ! 슈퍼클래스와 서브클래스의 name값이 각각 다를 때 super.draw()는 슈퍼클래스의 name을 , 서브클래스의 draw()는 서브클래스의 name을 출력함

 
 
 
<오버로딩과 오버라이딩>

오버로딩오버라이딩
(같은 클래스나 상속관계에서)매개변수의 타입이나 개수가 다른 여러 개의 메소드가 같은 이름으로 작성됨슈퍼클래스와 메소드 이름,매개타입,리턴타입이 모두 동일한 메소드가 서브클래스에서 재정의됨
정적 바인딩 - 컴파일 시에 중복된 메소드 중 호출된는 메소드 결정동적 바인딩 - 실행 시간에 오버라이딩된 메소드  찾아서 호출

 
 
 
<추상메소드와 추상클래스>

  • 추상 메소드 : 선언되어 있으나 구현되어있지 않은 메소드, abstract로 선언 (public abstract String name();) 
  • 추상메소드는 서브클래스에서 오버라이딩하여 구현해야 함
  • 추상클래스의 종류 : 추상메소드를 하나라도 가진 클래스 (클래스 앞에 abstract라고 선언해야함) / 추상메소드가 없지만 abstract로 선언된 클래스
  • 추상클래스는 객체를 생성할 수 없음
  • 추상클래스의 단순 상속 : 추상클래스를 상속받아 추상메소드를 구현하지 않으면 추상클래스 됨 / 서브클래스도 abstract로 선언해야함 / 서브클래스의 객체 또한 생성 불가
  • 추상클래스의 구현 상속 : 서브클래스에서 슈퍼클래스의 모든 추상메소드 구현(오버라이딩) / 서브클래스는 추상클래스가 아님 / 서브클래스 객체 생성 가능
  • 추상클래스의 목적 : 슈퍼클래스에서는 개념을 정의하고 서브클래스마다 각자 다르게 구현할 때 / 객체 생성이 목적이 아니라 슈퍼클래스로 사용할 클래스를 만드는게 목적일 때
추상클래스 구현 예제 : 33-34줄은 그냥 array 부분에 new int [] {1,2,3,4,5} 로 대체 가능

 
 
<인터페이스>

  • 인터페이스 : 클래스가 구현'해야' 하는 메소드들이 선언되는 추상형 클래스
  • interface 키워드로 선언 (public interface inter{} )
  • 인터페이스의 멤버 : 상수, 추상 메소드(abstract 생략 가능). default 메소드, private메소드, static 메소드
  • 필드(멤버변수)는 만들 수 없음
  • 상수는 public static final  속성이며, 속성은 생략 가능
  • 추상메소드 속성은 public abstract로 정해져 있으며 생략 가능 (둘 중 하나만 생략해도 됨)
  • default메소드의 접근 지정은 public으로 고정되어 있다 / 인터페이스를 구현하는 클래스에 자동상속
  • private메소드는 인터페이스 내의 다른 메소드에서만 호출 가능
  • static 메소드는 public과 private 모두 가능하고 생략 시엔 public                                      
  • default , private, static 메소드들은 코드가 작성되어 있어야 함
  • 인터페이스는 객체를 만들 수 없음
  • 인터페이스 타입의 레퍼런스 변수 선언 가능
  • 인터페이스를 상속받은 클래스는 인터페이스의 모든 추상메소드 반드시 구현
  • 다른 인터페이스 상속 가능 - extends 키워드 이용
  • 클래스는 하나 이상의 인터페이스 구현 가능(class a implements a,b {   } )
  • 인터페이스는 다중상속 가능 ( interface a extends b, c{ } )
  • 인터페이스 상속받을 때는 implements 키워드 가능
  • 이미 구현되어 있는 메소드들은 그대로 물려받음(private 제외)

 
 
<추상클래스와 인터페이스>

  • 유사점 : 객체 생성이 불가능하고 상속을 위한 슈퍼클래스로만 사용 , 클래스의 다형성 실현을 위한 기능들, 메소드의 선언만 있고 구현내용이 없음(추상메소드) , 추상메소드를 포함한 추상클래스 또는 인터페이스를 상속받았다면 반드시 재정의(오버라이드) 해야함
  • 차이점 

 

추상클래스인터페이스
추상클래스를 상속받아 기능을 이용하고 확장시키는데에 목적이 있음함수의 껍데기만 있고 구현을 강제함
객체들에 대해 동일한 동작을 보장하기 위해 존재
추상메소드와 일반 메소드 포함추상메소드, private메소드, default메소드, static 메소드로 구성
상수, 변수필드 모두 포함상수(public만 가능, public static final  생략가능)는 포함하지만 일반변수는 포함 x
is kind of 의 의미 (상속: 재사용+확장)is able to 의 의미
관련성이 높은 클래스 간에 코드를 공유하고 싶은 경우 사용관련성이 없는 클래스들이 같은 기능을 하게  하고싶은 경우 사용
 추상클래스보다 추상화 정도가 높음(처음엔 모든 메소드가 abstract였으나 이후 static메소드와 default메소드는 구현한 상태로 이용 가능하게 됨)
다중상속 불가 (여러개의 추상클래스 상속 불가)다중상속 지원
접근지정자 제한 없음protected 접근지정 선언 불가
생성자가 존재생성자가 없음

 

추상클래스 생성자 있는 예시
서브클래스에서 super()로 추상클래스 생성자에 접근해서 생성자를 사용할 수 있다(상속대상은 아니지만)
 
#추상클래스 객체는 생성 못하지만 추상클래스 타입의 구현클래스 객체는 생성 가능? 
 
<추가 주의점>

  • 단축키 잘 쓰기 : 우클릭-source-generate or alt+shift+s 보면 생성자랑 getter setter 생성해줌
  • 클래스 이름 뒤에 () 붙이는거 주의하기
  • super()은 바로 위 슈퍼클래스에만 가능
  • 인터페이스에서 상속받은 추상메소드 구현시엔 public으로 접근지정자 하기 - 추상메소드는 접근지정자가 public으로 고정되어 있는데, 접근지정자가 자식클래스에서 범위축소가 일어나면 안됨
  • 객체 안만들고 메소드 쓰게 한다 = static !!!! -> 인터페이스에서도 가능
  • 인터페이스 문제는 인터페이스에서 static,추상,default.private 메소드 작성하고 그거 상속받은 클래스에서 추상메소드 구현+새 메소드 추가하는 흐름
  • get,set메소드 구현해야하면 get  뒤의 이름으로 변수 설정하기(단축키 쓰기위해서)
  • 접근지정자의 디폴트와 인터페이스의 default메소드의 디폴트는 서로 다른 의미 !! 인터페이스 메소드의 default는 접근지정자의 의미가 아니라 바디가 작성된 메소드를 뜻함
  • 인터페이스의 디폴트메소드 또한 상속과 오버라이딩 가능 
  • 상속관계 있을때는 기본생성자 무조건 추가(에러방지위함)


<문제 모음>
 

코드 다시 생각해보기 !! 처음에 calc메소드에 input 넣어서 입력문구가 2번 출력됨
실행문에서 호출하는 run 메소드에 input과 calc 실행이 포함되어 있고 우리는 그 중 calc메소드를 작성하는거임
메소드에서 어떤 멤버변수 사용한다고 해서 그게 꼭 매개변수로 들어와야하거나 그 메소드에서 해당 변수를 구해야하는건 아님 ! 객체가 값을 갖고있을 멤버라면 그냥 사용하면 됨
 
 
<수업>
인터페이스 타입의 레퍼런스 변수는 선언 가능
인터페이스끼리 상속 가능 (extends 키워드 이용, 다중상속 가능함)
클래스가 인터페이스 여러개 구현할 수 있음
dufault 가 코드 있는 메소드면 생각해보니 그냥 public 메소드도 구현이 가능한 셈 / 단 default 메소드 선언 시 public은 생략 가능하지만 default 는 생략 불가능함
 
 

인터페이스에 디폴트 메소드만 선언되어있는 예시
디폴드메소드이 default 키워드는 생략 불가
인터페이스를 상속받은 클래스에서 오버라이딩하거나 생성할 메소드가 없더라도 생성자는 만들어야 객체 생성 , 사용이 가능 ( 물론 기본생성자만 필요하다면 클래스 바디가 비어있어도 됨)