다시 풀어보기 : (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가 다 있어야 하는건 아니고 필요에 따라 코드짜면 됨)
- 슈퍼클래스의 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. 으로 접근가능
서브클래스 객체를 슈퍼클래스 타입으로 정의 (업캐스팅) , 슈퍼클래스의 시선에서 보더라도 객체의 실체는 서브클래스이기 때문에 오버라이딩된 서브클래스의 메소드가 호출됨 = 동적 바인딩 !
<오버로딩과 오버라이딩>
오버로딩 | 오버라이딩 |
(같은 클래스나 상속관계에서)매개변수의 타입이나 개수가 다른 여러 개의 메소드가 같은 이름으로 작성됨 | 슈퍼클래스와 메소드 이름,매개타입,리턴타입이 모두 동일한 메소드가 서브클래스에서 재정의됨 |
정적 바인딩 - 컴파일 시에 중복된 메소드 중 호출된는 메소드 결정 | 동적 바인딩 - 실행 시간에 오버라이딩된 메소드 찾아서 호출 |
<추상메소드와 추상클래스>
- 추상 메소드 : 선언되어 있으나 구현되어있지 않은 메소드, abstract로 선언 (public abstract String name();)
- 추상메소드는 서브클래스에서 오버라이딩하여 구현해야 함
- 추상클래스의 종류 : 추상메소드를 하나라도 가진 클래스 (클래스 앞에 abstract라고 선언해야함) / 추상메소드가 없지만 abstract로 선언된 클래스
- 추상클래스는 객체를 생성할 수 없음
- 추상클래스의 단순 상속 : 추상클래스를 상속받아 추상메소드를 구현하지 않으면 추상클래스 됨 / 서브클래스도 abstract로 선언해야함 / 서브클래스의 객체 또한 생성 불가
- 추상클래스의 구현 상속 : 서브클래스에서 슈퍼클래스의 모든 추상메소드 구현(오버라이딩) / 서브클래스는 추상클래스가 아님 / 서브클래스 객체 생성 가능
- 추상클래스의 목적 : 슈퍼클래스에서는 개념을 정의하고 서브클래스마다 각자 다르게 구현할 때 / 객체 생성이 목적이 아니라 슈퍼클래스로 사용할 클래스를 만드는게 목적일 때
<인터페이스>
- 인터페이스 : 클래스가 구현'해야' 하는 메소드들이 선언되는 추상형 클래스
- 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 키워드는 생략 불가
인터페이스를 상속받은 클래스에서 오버라이딩하거나 생성할 메소드가 없더라도 생성자는 만들어야 객체 생성 , 사용이 가능 ( 물론 기본생성자만 필요하다면 클래스 바디가 비어있어도 됨)
'언어 공부 내용 정리 > Java' 카테고리의 다른 글
객지프 기말대비 정리 (6장) (0) | 2023.07.16 |
---|---|
객지프 기말대비 정리 (3-4장) (0) | 2023.07.15 |
객지프 중간대비 복습자료 (0) | 2023.07.07 |
자바 BufferedReader BufferedWriter : 빠른 입출력 (ing) (0) | 2023.06.28 |
자바 예외처리 (0) | 2023.06.17 |