** 2022년 10월 11일에 작성한 글입니다. **
📌 클래스 상속
클래스 상속?
포괄적인 속성/행위를 갖는 클래스로 구현을 하고 싶으면서 독립적인 클래스로 구현하고 싶을 때 클래스 상속을 해줍니다. 즉, 개별적인 클래스를 정의하면서 (1) 반복적인 코드는 최소화 (2) 비슷한 행위는 공통의 인터페이스 사용 (3) 객체를 명확히 구분하고 싶을 때 클래스 상속을 통해 이를 해결할 수 있습니다.
상속의 이점
- 코드의 재사용이 가능합니다.
- 검증된 코드의 재사용으로 오류를 최소화합니다.
- 소스 코드의 관리와 유지보수가 용이합니다.
- 개발 시간을 단축해줍니다.
- ⭐ 연관된 일련의 클래스에 대한 공통 규약을 정의합니다.
- 클래스 객체 간의 동작을 통일시켜 간결성을 제공해줍니다.
공통점을 갖고 있지만 서로 다른 클래스들을 상속을 기반으로 설계하여 각 객체들간의 동작이나 특성을 통일성있게 유지하며 소스코드와 유지 보수를 쉽게 이룰 수 있습니다.
IS-A 관계
IS-A(~중의 하나) 관계가 성립할 때 상속을 기반으로 표현할 수 있습니다.
📌 JAVA 클래스 상속
JAVA 클래스 상속 특징
- JAVA의 모든 클래스는 Object 클래스로부터 파생됩니다.
- 단일 상속만 제공됩니다.
- private 멤버일 경우 상속은 되나 직접 참조는 불가능합니다. access 메서드(getter, setter)를 이용하면 접근할 수 있습니다.
- 하위 클래스의 생성자 첫 줄에서 상위 클래스의 생성자를 명시적으로 호출합니다.
super 클래스 vs sub 클래스
- super 클래스 : 상위클래스로 자신의 멤버들을 상속해주는 클래스입니다.
- sub 클래스 : 하위클래스로 super 클래스로부터 멤버들을 상속 받는 클래스입니다.
protected, private 접근 지정자
Person 클래스가 super 클래스이며 UnivStudent가 sub 클래스입니다.
보통 Person 클래스의 멤버는 protected 접근 지정자로 선언하여 다른 패키지에 있는** 하위 클래스가 멤버에 접근이 가능하도록 해줍니다. 만일 **private 접근 지정자로 선언해 주었다면 access 메서드(getter, setter)를 사용하여 접근할 수 있습니다.
//basicpk/Person.java
package basic;
public class Person {
protected int age;
private String name;
//access 메서드
public int getAge() {
return age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
//일반 메서드
public void WhatYourName() {
System.out.println(name);
}
public void HowOldAreYou() {
System.out.println(age+"세");
}
}
자식 클래스인 UnivStudent는 부모 클래스의 멤버와 메서드를 모두 상속받았습니다. UnitStudent에서 멤버를 따로 선언하는 것이 가능합니다.
Person name이 default, public,protected 일 때는 직접 참조가 가능하여 name이라고만 작성해도 됩니다. 하지만 private일 때는 직접 참조가 불가능하여 this.getName()을 통해 접근이 가능합니다.
//basicpk/UnivStudent.java
package basic;
public class UnivStudent extends Person{
public String major;
public void WhoAreYou() {
System.out.println(this.getName());
System.out.println(age+"세"); //age가 protected이니 접근 가능
System.out.println(this.major+"전공");
}
}
위와 마찬가지로 main에서 객체를 선언주고 멤버에 접근할 때 age는 protected이니 s.age로 작성이 가능합니다. 하지만 name은 private이니 s.setName처럼 access 메서드를 통해 접근이 가능합니다.
//basicpk//StudentTest.java
import basic.UnivStudent;
public class StudentTest {
public static void main(String[] args) {
UnivStudent s=new UnivStudent();
s.age(20);
s.setName("홍길동");
s.major="컴퓨터공학";
s.WhoAreYou();
}
}
📌 메서드 재정의
메서드 오버라이딩
- sub클래스에서 super 클래스에서와 같은 이름의 멤버를 다시 정의합니다.
- 기존의 멤버를 sub클래스에서 수정을 합니다.
- super 클래스에서 상속된 멤버는 은폐됩니다.
- 은폐된 멤버에 접근을 하고 싶을 때는 super 참조변수를 이용합니다.
this vs super
- this
- 부모 클래스로부터 상속받은 멤버는 자식 클래스에서 this 참조변수로 접근이 가능합니다.
부모로부터 상속받은 것이 자식 클래스의 멤버이기 때문입니다.
-
- super
- 메서드 오버라이딩으로 은폐된 상위 클래스의 메서드를 호출할 때 사용합니다.
java.lang.Object
특별히 상속관계를 명시하지 않았을 때 기본적으로 Object로부터 상속됩니다.
Person 클래스가 super 클래스이며 UnivStudent가 sub 클래스입니다.
@override
toString으로 재정의된 함수임을 나타내줍니다.
- 재정의하면 좋을 Object 클래스의 메서드
- String toString() : 현재 객체를 문자열로 표현합니다.
//overridingpk/Person.java
package overriding;
public class Person {
protected int age;
protected String name;
public void WhatYourName() {
System.out.println(name);
}
public void HowOldAreYou() {
System.out.println(age+"세");
}
public void WhoAreYou() {
WhatYourName();
HowOldAreYou();
}
@Override //다음의 함수는 toString으로 재정의된 함수이다를 나타내줌
public String toString() {
return name+"("+age+"세)";
}
}
자식 클래스에서 부모 클래스에서와 같은 이름의 메서드를 선언해 주는 것을 메서드 오버라이딩이라고 합니다. WhoAreYou()는 super 클래스에도 있지만 sub 클래스에서도 따로 정의를 하고 싶을 때 다음과 같이 작성이 가능합니다. 자식 클래스에서 WhoAreYou() 메서드를 재정의 해주니 부모한테 상속받은 WhoAreYou()는 은폐됩니다. 하지만 부모 클래스의 WhoAreYou()메서드를 사용을 하고 싶다면 super를 작성해주어 불러올 수 있습니다.
Object 클래스의 메서드인 String toString()도 super 참조변수를 이용하여 재정의가 가능합니다. 문자열에 넣고 싶은 내용도 추가할 수 있습니다.
//overridingpk/UnivStudent.java
package overriding;
public class UnivStudent extends Person{
protected String major;
public void WhoAreYou() {
super.WhoAreYou();
System.out.println(major+"전공");
}
@Override
public String toString() {
return super.toString()+" " +major+"전공 대학생";
}
}
main에서는 문자열을 출력하듯이 생성한 참조변수를 출력해줄 수 있습니다.
System.out.prinln(s)처럼 작성이 가능합니다.
//overridingpk//StudentTest.java
package overriding;
public class StudentTest {
public static void main(String[] args) {
UnivStudent s=new UnivStudent();
s.age=20;
s.name="홍길동";
s.major="컴퓨터공학";
//s.WhoAreYou();
System.out.println(s); //문자열처럼 출력하고 싶을 때
//s는 s.toString()과 같음
System.out.println(s.toString());
}
}
📌 하위 클래스의 생성자
상속과 생성자
- 생성자를 이용하여 객체 생성과 동시에 각 멤버변수의 값을 초기화할 수 있습니다.
- 하위 클래스 객체를 위한 생성자는 항상 하위 클래스에서 새롭게 정의를 해야 합니다.
하위 클래스의 생성자 구현
⭐ 상위 클래스의 생성자 호출을 통해 상속받은 멤버 변수들을 초기화 해야합니다.
하위 클래스의 생성자를 미구현시 자동으로 상위 클래스의 인자 없는 생성자가 호출됩니다.
super([인수리스트])
- 상위 클래스 생성자를 호출할 때 사용합니다.
- 반드시 하위 클래스 생성자의 첫 줄에 위치해야 합니다.
- 하위 클래스의 생성자 안에 이 호출이 명시적으로 포함되어
- 있으면
- 상위 클래스의 인자 없는 생성자의 자동 호출은 생략됩니다.
- 없으면
- 상위 클래스의 인자 없는 생성자의 자동 호출이 일어납니다.방법
- 있으면
- 인자 없는 생성자를 추가할 경우 아래 과정은 생략해줍니다. 자동으로 이루어지기 때문입니다.
- 상위 클래스에서 인자 있는 생성자를 추가해줍니다.
public Person(String name, int age) { this.age=age; this.name=name; }
- 하위 클래스 생성자의 첫번째 줄에 상위 클래스 생성자를 호출합니다.
public UnivStudent(String name, int age, String major){ super(name, age); }
- 하위 클래스의 멤버는 this 참조변수를 이용하여 초기화해줍니다.
this.major=major;
- main에서 생성자를 초기화해줍니다.
UnivStudent s=new UnivStudent("홍길동",20,"컴퓨터공학");
전체 코드는 다음과 같습니다.
//superpk/Person.java
package superpk;
public class Person {
protected int age;
protected String name;
public Person(String name, int age) {
this.age=age;
this.name=name;
}
public void WhatYourName() {
System.out.println(name);
}
public void HowOldAreYou() {
System.out.println(age+"세");
}
public void WhoAreYou() {
WhatYourName();
HowOldAreYou();
}
@Override
public String toString() {
return name+"("+age+"세)";
}
}
//superpk/UnivStudent.java
package superpk;
public class UnivStudent extends Person{
protected String major;
public UnivStudent(String name, int age, String major) {
super(name, age);
this.major=major;
}
public void WhoAreYou() {
super.WhoAreYou();
System.out.println(major+"전공");
}
@Override
public String toString() {
return super.toString()+" " +major+"전공 대학생";
}
}
//superpk//StudentTest.java
package superpk;
public class StudentTest {
public static void main(String[] args) {
UnivStudent s=new UnivStudent("홍길동",20,"컴퓨터공학");
s.WhoAreYou();
}
}
💡 하위 클래스 작성시 유의점
- private 멤버는 상속은 되나 직접 참조는 불가합니다. -> access 메서드를 이용합니다.
- 하위 클래스의 생서자 첫 줄에서 상위 클래스의 생성자를 명시적으로 호출합니다.
- 재정의 되어 은폐된 멤버는 super, 나머지 멤버는 this 참조변수로 접근합니다.
'개발 > JAVA' 카테고리의 다른 글
[JAVA] Swing 기본 (0) | 2023.04.11 |
---|---|
[JAVA] 예외처리 (0) | 2023.04.11 |
[JAVA] 배열 (0) | 2023.04.11 |
[JAVA] 클래스와 객체 & 멤버 (0) | 2023.04.11 |
[JAVA] 기본 구조와 자료형 (0) | 2023.04.11 |