Java에는 자식 클래스가 부모 클래스의 기능을 그대로 물려받을 수 있는 상속(Inheritance)기능이 있다.
- 상속하는 클래스를 부모 클래스, 상위 클래스, 기초 클래스,슈퍼 클래스라 부른다.
- 상속받는 클래스를 자식 클래스, 하위 클래스, 유도 클래스,서브 클래스라 부른다.
상속(Inheritance)은 객체지향 프로그래밍(OOP: Object Oriented Programing)에서 가지는 특징 중 하나로 부모가 자녀에게 변수(variable)와 메서드(method)를 물려주는 것을 말한다. 사용키워드는 "extends" 다.
본격적으로 상속을 사용해보기 위해 예제코드를 살펴보자. 프로토스 클래스는 부모 클래스로 프로토스 유닛들은 모두 기본 공격을 할 수 있다.
public class Protoss {
public void attack() {
System.out.println("기본공격");
}
}
그리고 프로토스의 기본 유닛인 질럿 클래스를 살펴보자.
public class Zealot extends Protoss{
}
질럿은 "extends" 키워드를 통해 프로토스 클래스를 물려받을 수 있다. 질럿 클래스에는 키워드를 제외하고 아무것도 적혀있지 않지만 출력해보면 실제로 기본공격이 출력되는 것을 볼 수 있다.
public class Gate {
public static void main(String[] args) {
Zealot zealot = new Zealot();
zealot.attack();
}
}
하지만 이는 단순하게 기본공격으로 출력될 뿐 유닛들만의 특색이 없다는 것을 쉽게 알 수 있다. 이런 경우 질럿만의 특색을 살려주기 위해 우리는 오버라이딩(Overridng)을 통해 질럿만의 특색을 살릴 수 있다.
public class Zealot extends Protoss{
@Override
public void attack() {
System.out.println("찌르기");
}
}
기본적으로 상속을 사용하는 방법을 알아봤다. 그렇다면 이런 상속을 이용하는 이유는 무엇일까?
1. 상속의 필요성
① 기존 클래스의 변수와 코드를 재사용할 수 있어 개발 시간이 단축된다.
② 먼저 작성되어 검증된 프로그램을 재사용하기 때문에 신뢰성 있는 프로그램을 개발할 수 있다.
③ 클래스 간 계층적 분류 및 관리가 가능하여 유지보수가 용이하다.
상속(Inheritance)를 사용하는 큰 이유는 재사용이며 이는 곧 유지보수의 용이성으로 이어지기 때문이다. 하지만 꼭 장점만 있는 것은 아니다. 상속을 사용함에 따라 객체지향을 복잡하게 하는 주요 원인이 되기도 한다.이런 필요성을 기억하고 상속의 특징도 살펴보자.
2. 상속의 특징
① 자바에서는 클래스의 다중상속을 지원하지 않는다.
public class Zealot extends Protoss, Zerg{
@Override
public void attack() {
System.out.println("찌르기");
}
}
이런 경우는 불가능하며 extends 다음에는 클래스 이름 하나만 지정할 수 있다.
② 자바에서는 상속의 횟수에 제한을 두지 않는다.
③ 자바에서 계층구조의 최상위에는 java.lang.Object 클래스가 있다.
자바에서 모든 클래스는 Object클래스를 자동으로 상속받도록 되어있다.
toString(), equals()와 같은 메소드를 바로 사용할 수 있다.
3. super
super는 상속에서 알고가야 하는 개념 중 하나로 자신이 상속받은 부모 클래스에 대한 레퍼런스 변수를 말한다.
용도는 부모 클래스의 멤버에 접근할 때 사용된다. 주로 객체안에 있는 부모의 멤버변수와 자신의 멤버변수를 구별하기 위해 사용된다는 것도 알고있으면 좋다. super는 알겠는데 super()은 무엇일까? super()은 자식 클래스의 생성자에서 부모 클래스의 생성자를 호출하기 위해서 사용된다. 이런 super()은 다음과 같은 특징을 가지고 있다.
① super()는 생성자 코드안에서 사용 될 때 다른 코드에 앞서 첫줄에 사용되어야 한다.
② 자식 클래스의 모든 생성자는 부모 클래스의 생성자를 포함하고 있어야 한다.
②에서 자식 클래스의 생성자는 부모 클래스의 생성자를 포함하고 있어야 한다 했다. 그런데 만약 자식 클래스의 생성자에 부모 클래스의 생성자가 포함되어 있지 않다면 컴파일러가 자동으로 부모 클래스의 기본생성자를 호출한다. 하지만 이런 경우 부모 클래스에 매개변수가 있는 생성자만 있고 기본 생성자가 없는 경우 에러가 발생한다. 아래 예제를 통해 해당 내용을 정리해보자.
public class Protoss {
private String name="Zealot";
private String money ="100";
public String getZealot() {
return this.name + "/" + this.money;
}
}
프토토스 클래스가 위와 같다고 가정하자. 그리고 게이트 클래스는 다음과 같다고 보자.
public class Gate {
public static void main(String[] args) {
Protoss unit = new Protoss();
System.out.println(unit.getZealot());
}
}
프로토스 클래스의 인스턴스인 unit은 기본 생성자를 사용해 생성된다. 하지만 기본 생성자는 아무런 동작도 하지 않으므로 인스턴스 변수를 프로토스 클래스 필드에서 바로 초기화하고 있다. 이처럼 인스턴스 변수의 초기화는 생성자를 사용해 수행할 수 도 있지만 클래스 필드에서도 바로 수행할 수 있다. 하지만 매개변수를 가지는 생성자를 하나라도 정의했다면 기본 생성자는 자동으로 추가되지 않아 오류가 발생한다.
public class Protoss {
private String name;
private String money;
public Protoss(String name, String money) {
super();
this.name = name;
this.money = money;
}
public String getZealot() {
return this.name + "/" + this.money;
}
}
매개변수를 가지는 생성자를 추가 했다면 게이트 클래스도 다음과 같이 수정되어야 실행된다.
public class Gate {
public static void main(String[] args) {
Protoss protoss = new Protoss("Zealot","100");
System.out.println(protoss.getZealot());
}
}
3. this
this는 객체 자신을 가리키는 레퍼런스 변수로 자신의 객체에 접근할 때 사용한다. 주로 멤버변수와 매개변수의 이름이 동일할 때 이를 구분하기 위해 사용된다. this는 알겠는데 this()는 무엇일까? this()는 같은 클래스에서 생성자가 다른 생성자를 호출할 때 사용한다. 이런 this()는 다음과 같은 특징을 가지고 있다.
① 주로 코드의 중복을 줄일 목적으로 사용한다.
② this()는 생성자 코드에서만 사용할 수 있다.
③ this()는 생성자 코드안에서 사용될 때 첫번째 문장으로 다른 코드보다 가장 윗줄에 위치해야 한다.
설명을 위해 다시 프로토스 클래스를 불러보자.
public class Protoss {
private String name;
private String money;
public void Unit(String name, String money) {
this.name=name;
this.money=money;
}
}
프로토스 클래스는 멤버변수 즉 필드에 name과 money를 가지고 있다. 그리고 Unit 메서드는 멤버변수와 동일한 이름의 변수를 매개변수로 가진다. 이럴때 this를 사용하여 name과 money를 특정해주는 것이다. this.name과 this.money는 클래스 필드의 변수이고 name과 money는 Unit 메서드의 매개변수이다 라는 것을 말이다.
물론 변수 이름을 다르게 하면 this를 사용하지 않아도 된다. 하지만 코드의 직관성을 위해 사용하는 것을 권장하고 있다.
'Java' 카테고리의 다른 글
[Java] AtomicLong (0) | 2023.01.27 |
---|---|
[Java] Record Class (0) | 2023.01.27 |
[Java] Arrays.sort (0) | 2023.01.12 |
[Java] indexOf/lastIndexOF (0) | 2023.01.12 |
[Java] OOP(ObejectOrientedProgramming) (1) | 2022.12.05 |