클래스의 상속
자바 클래스의 상속 (Inheritance)에 대한 기본 개념
자바에서 클래스의 상속은 객체 지향 프로그래밍의 중요한 개념 중 하나입니다. 상속은 코드의 재사용성과 계층적인 구조를 구현하는 데 도움을 주며, 객체 지향 프로그래밍의 특징 중 하나인 "부모 클래스와 자식 클래스" 관계를 정의하는 데 사용됩니다.
부모 클래스 (Parent Class)와 자식 클래스 (Child Class)
부모 클래스는 다른 클래스에서 상속 받을 수 있는 기본 틀을 정의합니다. 자식 클래스는 부모 클래스를 확장하고, 부모 클래스의 모든 멤버 변수와 메서드를 상속받아 사용할 수 있습니다. 이것은 중복 코드를 줄이고 유지보수성을 향상시킵니다.
extends 키워드 사용
자식 클래스를 정의할 때, extends 키워드를 사용하여 어떤 부모 클래스를 상속받을지 지정합니다. 아래는 간단한 예제입니다.
class 부모클래스 {
// 부모 클래스의 멤버 변수와 메서드 정의
}
class 자식클래스 extends 부모클래스 {
// 자식 클래스에서 추가적인 멤버 변수와 메서드 정의
}
상속 관련 다양한 호칭
상속 대상 클래스 호칭 | 상속을 받은 클래스 호칭 |
슈퍼 클래스(Super Class) | 서브 클래스(Sub Class) |
부모 클래스(Parent Class) | 자식 클래스(Child Class) |
기반 클래스 | 파생 클래스 |
조상 클래스 | 자손 클래스 |
상위 클래스 | 하위 클래스 |
부모 클래스의 멤버 변수와 메서드 활용
자식 클래스는 부모 클래스의 멤버 변수와 메서드를 직접 사용할 수 있습니다. 또한, 자식 클래스는 부모 클래스의 메서드를 재정의(Override)하여 자신의 동작을 정의할 수도 있습니다.
다형성 (Polymorphism)
상속을 통해 자식 클래스는 부모 클래스의 객체로 사용될 수 있으며, 다형성을 구현할 수 있습니다. 이것은 프로그램의 유연성을 높이고, 코드를 더 추상화하여 설계할 수 있도록 도와줍니다.
자바의 클래스 상속은 객체 지향 프로그래밍의 핵심 요소 중 하나이며, 코드의 재사용과 구조화에 큰 도움을 줍니다. 상속을 적절히 활용하면 더 모듈화된, 유지보수가 쉬운 코드를 작성할 수 있습니다.
아래는 실제코드 예제 입니다.
class Unit{ // 부모 클래스
String name;
int hp;
void printUnit(){
System.out.println("이름 : " + name);
System.out.println("HP : " + hp);
}
}
class Warrior extends Unit{ // 자식 클래스
int attack;
void printWarrior(){
printUnit();
System.out.println("공격력 : " + attack);
}
}
class healer extends Unit{ // 자식 클래스
int heal;
void printHealer(){
printUnit();
System.out.println("치유량 : " + heal);
}
}
public class MyCharacter{
public static void main(String[] args){
Warrior unit1 = new Warrior(); // 객체 생성
unit1.name = "전사";
unit1.hp = 100;
unit1.attack = 20;
healer unit2 = new healer();
unit2.name = "클래릭";
unit2.hp = 120;
unit2.heal = 10;
unit1.printWarrior();
System.out.println();
unit2.printHealer();
}
}
실행 결과
instanceof 연산자란?
instanceof 연산자는 객체가 특정 클래스나 인터페이스의 인스턴스인지 확인하는 Java의 키워드입니다.
이 연산자는 객체 지향 프로그래밍에서 객체 간의 상속 및 계층 구조를 고려할 때 유용하게 활용됩니다.
if (object instanceof ClassName) {
// object는 ClassName의 인스턴스입니다.
} else {
// object는 ClassName의 인스턴스가 아닙니다.
}
위 코드에서 object는 확인하려는 객체이고, ClassName은 객체가 속한 클래스나 인터페이스의 이름입니다.
instanceof 연산자 사용 예제
클래스 확인하기
class Animal {}
class Dog extends Animal {}
Animal myDog = new Dog();
if (myDog instanceof Animal) {
System.out.println("myDog은 Animal 클래스의 인스턴스입니다.");
}
if (myDog instanceof Dog) {
System.out.println("myDog은 Dog 클래스의 인스턴스입니다.");
}
인터페이스 확인하기
interface Shape {}
class Circle implements Shape {}
Shape myCircle = new Circle();
if (myCircle instanceof Shape) {
System.out.println("myCircle은 Shape 인터페이스의 인스턴스입니다.");
}
if (myCircle instanceof Circle) {
System.out.println("myCircle은 Circle 클래스의 인스턴스입니다.");
}
instanceof 연산자의 활용
- 다형성 (Polymorphism): instanceof 연산자를 사용하여 객체의 실제 유형을 확인하고, 그에 따라 다른 동작을 수행할 수 있습니다.
- 타입 캐스팅: 객체를 특정 클래스나 인터페이스로 캐스팅하기 전에 'instanceof'를 사용하여 안전성을 확보할 수 있습니다.
예제를 만들고 어떻게 사용하는지 알아보겠습니다.
interface Cry{
void cry();
}
class Tiger implements Cry{
public void cry(){
System.out.println("어흥~");
}
}
class Wolf implements Cry{
public void cry(){
System.out.println("아우~~!");
}
}
public class Instanceof{
public static void main(String[] args){
Cry test1 = new Tiger();
if (test1 instanceof Tiger){
test1.cry();
}else if (test1 instanceof Wolf){
System.out.println("호랑이가 아닙니다.");
}
}
}
실행 결과
주의사항
instanceof 연산자를 남용하지 않도록 주의해야 합니다. 이는 객체 지향 설계를 잘못 이해한 결과로 이어질 수 있습니다.
대신, 상속 및 인터페이스 구조를 최대한 활용하여 다형성을 지원하도록 노력해야 합니다.