상속
- 상속
· 기존의 클래스를 재사용하여 새로운 클래스를 작성하는 것 → 코드의 추가 및 변경 용이함
∴ 코드의 재사용성↑, 중복 제거 → 유지보수 쉬워짐
☞ 첫번째 상속 예시
- 직접 2개의 클래스 ( ChildClass, ParentClass ) 생성해서 상속에 대해 알아보자
< ① ParentClass >
package inherit;
public class ParentClass {
// 멤버변수 선언
String name;
// 기본생성자
ParentClass(){
this.name = "자바";
}
// 속성함수
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
❶ SuperClass의 멤버 변수 선언
❷ 기본생성자를 통해 변수 초기화
❸ 속성함수를 통해 외부로부터 데이터 보호
< ② ChildClass >
package inherit;
public class ChildClass extends ParentClass {
// print() 메서드 추가
void print() {
System.out.println("자식클래스의 이름 : " + this.name);
}
}
❶ SuperClass를 상속받아보자
- 상속받는 방법
public class ChildClass extends ParentClass { }
→ 새로 작성할 클래스이름 extends 상속받고자 하는 클래스이름
∴ 두 클래스는 서로 상속관계에 있음
→ 부모 클래스의 모든 멤버를 상속받기 때문에, ChildClass는 ParentClass의 멤버들을 포함함
❷ Print( ) 메서드 추가
→ SuperClass의 멤버 이외에 Print( ) 메서드가 추가로 존재
< ③ InheritClass ( 실행클래스 ) >
package inherit;
public class InheritApp {
public static void main(String[] args) {
// 객체 생성
ParentClass parentClass = new ParentClass();
ChildClass childClass = new ChildClass();
// 부모 클래스 이름 출력
System.out.println("부모클래스의 이름 : " + parentClass.name );
// 부모 클래스 이름 변경 후, 출력
parentClass.setName("화이팅");
System.out.println("변경된 부모클래스의 이름 : " + parentClass.getName());
// 자식 클래스의 print() 메서드 호출
childClass.print();
// 자식 클래스 이름 변경 후, 출력
childClass.setName("아자");
childClass.print();
}
}
❶ 객체 생성
❷ ParentClass의 이름 출력 : 기본생성자를 통해 초기화된 이름이 출력됨
❸ 속성함수를 통해 ParentClass의 이름 변경 후, 다시 출력
❹ ChildClass의 print( ) 메소드 호출
→ 변수 name이 "자바" ( ParentClass에서 기본생성자를 통해 초기화된 이름 )으로 출력됨
∴ 상속을 통해 동일한 내용의 코드를 메모리에 따로 로드시키는 것이 아니라 한번만 로드시킨 후, 공유함
즉, 자식클래스의 경우 상속받은 멤버를 다시 메모리에 로드시키는 것이 아니라 부모클래스의 시작주소만 가지고 있는 상태
❺ 속성함수를 통해 ChildClass의 이름 변경 후 출력
< 출력 결과 >
부모클래스의 이름 : 자바
변경된 부모클래스의 이름 : 화이팅
자식클래스의 이름 : 자바
자식클래스의 이름 : 아자
▷ 이번 예시를 통해 알 수 있었던 내용
: 자식클래스에 새로운 코드가 추가되어도 부모클래스에는 아무런 영향을 미치지 않음
하지만, 부모클래스에서 변경될 경우 자식클래스에서 자동적으로 영향을 받게 됨
① 자손 클래스는 부모 클래스의 모든 멤버를 상속받음
( 단, 생성자와 초기화 블럭은 상속되지 않음 )
② 자손 클래스의 멤버 개수는 부모 클래스보다 항상 같거나 많음
( 질문 )
상속의 경우 생성자는 상속되지 않음 → 근데 자식 클래스에서 새로 추가한 print( ) 메서드 호출 시, name은 "자바"로 출력
⇒ 그럼 생성자가 상속되어서 자식클래스 객체 생성 시, "자바"로 초기화된 거 아닌가? 이럴경우, 디버그를 이용해보자.
< 디버그 이용 >
❶ Resume : 다음 Breakpoint로 넘어감
❷ Step Into : 한 줄씩 지나가며 메소드를 만날 경우에는 그 메소드 안까지 들어감
❸ Step Over : 한 줄씩 지나가며 메소드를 만날 경우에는 따라 들어가지 않고 진행
① InheritApp 클래스에서 객체 생성되는 부분
에 Breakpoint 지정 후, Debug 실행
② Step Into 클릭 → ParentClass에 있는 생성자 호출됨
③ 생성자에 의해 변수 name을 "자바"로 초기화됨
④ ChildClass의 객체 생성 → ParentClass의 name 변수를 공유함을 알 수 있음 ( 위치 동일 )
∴ 상속 시, 생성자는 상속되지 않음 -> 만약 생성자가 상속이 된다면, 두 클래스의 변수 name의 위치가 같을 수 없음.
⑤ ParentClass의 속성함수를 통해 데이터의 값을 변경 후 출력
⑥ ChildClass의 속성함수를 통해 데이터의 값 변경 후 출력
☞ 두번째 상속 예시
< ① Book Class >
package inherit;
public class Book {
// 멤버 변수
String name;
String author;
int price;
// 속성함수
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
// 출력 메서드
public void print() {
System.out.println(
"ParentBook의 이름 : " + this.name +
"\nParentBook의 저자 : " + this.author +
"\nParentBook의 가격 : " + this.price);
}
}
< ② ITBook Class >
package inherit;
public class ITBook extends Book {
// 멤버 변수 선언
String genre;
String publisher;
// 속성함수
public String getGenre() {
return genre;
}
public void setGenre(String genre) {
this.genre = genre;
}
public String getPublisher() {
return publisher;
}
public void setPublisher(String publisher) {
this.publisher = publisher;
}
// toString() 메소드 재정의
@Override
public String toString() {
String msg =
"ITBook [genre=" + genre +
", publisher=" + publisher +
", Name=" + this.getName() +
", Author=" + this.getAuthor() +
", Price=" + this.getPrice() +
"]";
return msg;
}
}
< ③ BookApp Class >
package inherit;
public class BookApp {
public static void main(String[] args) {
// 객체 생성
Book book = new Book();
ITBook itBook = new ITBook();
// 속성함수 이용해 부모클래스 변수의 데이터값 변경
book.setName("혼자 공부하는 자바");
book.setAuthor("신용권");
book.setPrice(20000);
// 부모클래스 출력
book.print();
// 속성함수를 이용해 자식클래스 변수의 데이터값 변경
itBook.setName("이것이 자바다");
itBook.setAuthor("신용권");
itBook.setPrice(30000);
itBook.setGenre("JAVA");
itBook.setPublisher("한빛출판사");
// 자식클래스 출력
System.out.println(itBook.toString());
}
}
< 출력 결과 >
ParentBook의 이름 : 혼자 공부하는 자바
ParentBook의 저자 : 신용권
ParentBook의 가격 : 20000
ITBook [genre=JAVA, publisher=한빛출판사, Name=이것이 자바다, Author=신용권, Price=30000]
+ 접근제어자로 접근 제한범위 설정해보기
- 접근 제어자의 목적 : 멤버 또는 클래스에 사용 → 해당 멤버 또는 클래스를 외부에서 접근하지 못하도록 제한하는 역할
- 접근 범위가 넓은 쪽에서 좁은 쪽의 순
: public > protected > (default) > private
① public : 접근 제한 없음
② (default) : 같은 패키지 내에서만 접근 가능 → 접근 제어자가 지정되어 있지 않은 경우에 해당
③ protected : 같은 패키지 내 또는 다른 패키지의 자손 클래스에서 접근 가능
④ private : 같은 클래스 내에서만 접근 가능
'백엔드 > JAVA' 카테고리의 다른 글
객체 지향 프로그래밍 이론(6) (0) | 2023.05.16 |
---|---|
13일차 수업 기록 (0) | 2023.05.15 |
MVC 패턴 개념 (0) | 2023.05.11 |
객체 지향 프로그래밍 이론(3) 및 주사위 게임 예제 실습 (0) | 2023.05.09 |
접근제어자 및 객체 지향 프로그래밍 (2) (0) | 2023.05.08 |