클래스 상속과 객체는 자바의 객체 지향 프로그래밍에서 중요한 개념입니다. 상속을 통해 클래스 간의 관계를 정의하고, 코드의 재사용성을 높이며, 더 나아가 객체 지향 프로그래밍의 기본 원칙 중 하나인 재사용성과 확장성을 지원합니다.
클래스 상속 (Inheritance)
클래스 상속은 기존 클래스(부모 클래스 또는 슈퍼클래스)의 특성을 새로운 클래스(자식 클래스 또는 서브클래스)가 물려받는 기능을 제공합니다. 상속을 통해 기존 클래스의 필드와 메서드를 재사용하고, 새로운 필드와 메서드를 추가하여 확장할 수 있습니다.
상속의 기본 개념
부모 클래스 (Superclass): 상속을 제공하는 클래스입니다. 부모 클래스는 공통된 속성과 기능을 정의합니다.
자식 클래스 (Subclass): 부모 클래스를 상속받아 기능을 확장하거나 변경하는 클래스입니다. 자식 클래스는 부모 클래스의 모든 공용 및 보호된 필드와 메서드를 상속받습니다.
형식:
java
코드 복사
public class ParentClass {
// 부모 클래스의 필드와 메서드
}
public class ChildClass extends ParentClass {
// 자식 클래스의 추가 필드와 메서드
}
상속의 예제
부모 클래스:
java
코드 복사
public class Animal {
String name;
public void eat() {
System.out.println(name + " is eating.");
}
}
자식 클래스:
java
코드 복사
public class Dog extends Animal {
public void bark() {
System.out.println(name + " is barking.");
}
}
사용 예:
java
코드 복사
public class Main {
public static void main(String[] args) {
Dog myDog = new Dog();
myDog.name = "Buddy";
myDog.eat(); // 부모 클래스의 메서드 호출
myDog.bark(); // 자식 클래스의 메서드 호출
}
}
이 예제에서 Dog 클래스는 Animal 클래스를 상속받아 name 필드와 eat() 메서드를 사용할 수 있으며, 추가로 bark() 메서드를 정의하고 있습니다.
상속의 주요 특징
코드 재사용: 자식 클래스는 부모 클래스의 필드와 메서드를 재사용할 수 있으므로 중복 코드를 줄이고 유지보수성을 높일 수 있습니다.
다형성: 상속을 통해 객체가 다양한 형태로 동작할 수 있으며, 부모 클래스의 참조 변수로 자식 클래스의 객체를 다룰 수 있습니다.
메서드 오버라이딩: 자식 클래스는 부모 클래스에서 상속받은 메서드를 재정의하여 자신만의 방식으로 구현할 수 있습니다.
super 키워드: 자식 클래스에서 부모 클래스의 필드나 메서드에 접근하거나 호출할 때 super 키워드를 사용할 수 있습니다.
예제:
java
코드 복사
public class Dog extends Animal {
public void eat() {
super.eat(); // 부모 클래스의 eat() 메서드 호출
System.out.println(name + " is eating dog food.");
}
}
객체와 상속
다형성: 상속을 활용하면 동일한 메서드 호출이 객체의 실제 클래스에 따라 다르게 동작할 수 있습니다. 이를 다형성(polymorphism)이라고 하며, 메서드 오버라이딩을 통해 구현할 수 있습니다.
상속과 객체 생성: 자식 클래스의 객체를 생성하면, 부모 클래스의 생성자도 호출됩니다. 자식 클래스는 부모 클래스의 필드와 메서드를 상속받으므로, 부모 클래스의 필드를 초기화하는 작업이 필요할 수 있습니다.
예제:
java
코드 복사
public class Animal {
String name;
public Animal(String name) {
this.name = name;
}
}
public class Dog extends Animal {
public Dog(String name) {
super(name); // 부모 클래스의 생성자 호출
}
public void bark() {
System.out.println(name + " is barking.");
}
}
public class Main {
public static void main(String[] args) {
Dog myDog = new Dog("Buddy");
myDog.bark(); // Buddy is barking.
}
}
이 예제에서 Dog 클래스는 Animal 클래스의 생성자를 호출하여 name 필드를 초기화합니다.
상속의 주의 사항
단일 상속: 자바는 단일 상속을 지원합니다. 즉, 한 클래스는 하나의 부모 클래스만 가질 수 있습니다. 그러나 여러 인터페이스를 구현할 수 있습니다.
상속과 캡슐화: 상속을 사용할 때는 부모 클래스의 내부 상태를 자식 클래스가 직접 접근하지 않도록 캡슐화 원칙을 준수하는 것이 좋습니다.
상속의 깊이: 깊은 상속 계층 구조는 코드의 이해와 유지보수를 어렵게 만들 수 있습니다. 상속 계층을 적절히 관리하는 것이 중요합니다.
final 클래스와 메서드: final로 선언된 클래스는 상속할 수 없으며, final로 선언된 메서드는 오버라이딩할 수 없습니다.
이러한 개념을 통해 자바의 클래스 상속을 효과적으로 활용하여 객체 지향 프로그래밍을 지원하고, 코드의 재사용성과 유지보수성을 향상시킬 수 있습니다.
5.5 업캐스팅과 instanceof 연산자
ChatGPT
자바에서 업캐스팅(Upcasting)과 instanceof 연산자는 객체 지향 프로그래밍에서 상속 및 타입 체크를 효율적으로 관리하는 데 중요한 역할을 합니다. 이 두 개념은 클래스 계층 구조를 활용하여 객체의 타입을 다루는 데 도움이 됩니다.
업캐스팅 (Upcasting)
업캐스팅은 자식 클래스의 객체를 부모 클래스의 타입으로 변환하는 것입니다. 자바에서는 자식 클래스의 인스턴스를 부모 클래스 타입으로 다룰 수 있으며, 이를 통해 다형성을 구현할 수 있습니다.
업캐스팅의 특징
자동 변환: 업캐스팅은 자바에서 자동으로 수행되며, 명시적인 형 변환이 필요하지 않습니다. 부모 클래스 타입의 변수에 자식 클래스 객체를 할당할 수 있습니다.
상위 클래스의 메서드만 접근 가능: 업캐스팅을 통해 부모 클래스의 참조 변수로 자식 클래스 객체를 다룰 때, 부모 클래스에 정의된 메서드만 호출할 수 있습니다. 자식 클래스에서 추가된 메서드는 사용할 수 없습니다.
예제
java
코드 복사
// 부모 클래스
public class Animal {
public void eat() {
System.out.println("Animal is eating.");
}
}
// 자식 클래스
public class Dog extends Animal {
public void bark() {
System.out.println("Dog is barking.");
}
}
// 업캐스팅 예제
public class Main {
public static void main(String[] args) {
Dog myDog = new Dog(); // 자식 클래스 객체 생성
Animal myAnimal = myDog; // 업캐스팅
myAnimal.eat(); // Animal 클래스의 메서드 호출
// myAnimal.bark(); // 컴파일 오류: Animal 클래스에는 bark() 메서드가 없음
}
}
여기서 myAnimal은 Animal 타입의 변수로 Dog 객체를 참조하지만, Dog 클래스에 정의된 bark() 메서드에 접근할 수 없습니다.
instanceof 연산자
instanceof 연산자는 객체가 특정 클래스의 인스턴스인지 확인하는 데 사용됩니다. 이를 통해 객체의 실제 타입을 확인하고, 타입에 따라 적절한 작업을 수행할 수 있습니다.
instanceof의 특징
타입 검사: 객체가 특정 클래스의 인스턴스인지 확인하며, 클래스 계층 구조를 기반으로 검사합니다.
null 안전성: 객체가 null일 경우 instanceof 연산자는 항상 false를 반환합니다.
형 변환 안전성: 객체가 특정 클래스의 인스턴스인지 확인한 후, 안전하게 형 변환을 수행할 수 있습니다.
형식
java
코드 복사
object instanceof ClassName
object는 검사할 객체입니다.
ClassName은 검사할 클래스입니다.
예제
java
코드 복사
public class Animal {
}
public class Dog extends Animal {
}
public class Cat extends Animal {
}
public class Main {
public static void main(String[] args) {
Animal myAnimal = new Dog();
if (myAnimal instanceof Dog) {
System.out.println("myAnimal is a Dog.");
} else {
System.out.println("myAnimal is not a Dog.");
}
if (myAnimal instanceof Animal) {
System.out.println("myAnimal is an Animal.");
}
if (myAnimal instanceof Cat) {
System.out.println("myAnimal is a Cat.");
} else {
System.out.println("myAnimal is not a Cat.");
}
}
}
출력:
csharp
코드 복사
myAnimal is a Dog.
myAnimal is an Animal.
myAnimal is not a Cat.
여기서 myAnimal은 Dog 객체이므로 instanceof 연산자를 사용하여 Dog과 Animal 클래스에 대한 타입 검사를 통과합니다. Cat 클래스에 대해서는 검사에 실패합니다.
업캐스팅과 instanceof 연산자의 조합
업캐스팅과 instanceof 연산자는 함께 사용하여 객체의 타입을 안전하게 확인하고, 적절한 메서드를 호출할 수 있습니다. 일반적으로 다음과 같은 패턴으로 사용됩니다:
java
코드 복사
public class Animal {
public void makeSound() {
System.out.println("Animal sound");
}
}
public class Dog extends Animal {
public void bark() {
System.out.println("Dog barks");
}
}
public class Main {
public static void main(String[] args) {
Animal myAnimal = new Dog(); // 업캐스팅
if (myAnimal instanceof Dog) {
Dog myDog = (Dog) myAnimal; // 다운캐스팅
myDog.bark(); // 안전하게 Dog 클래스의 메서드 호출
}
}
}
이 패턴에서는 instanceof 연산자를 사용하여 myAnimal이 Dog 클래스의 인스턴스인지 확인한 후, 다운캐스팅을 수행하여 Dog 클래스의 메서드에 접근합니다.
요약
업캐스팅: 자식 클래스의 객체를 부모 클래스 타입으로 변환하는 것으로, 자식 클래스의 기능은 사용할 수 없지만 부모 클래스의 메서드와 필드에 접근할 수 있습니다.
instanceof: 객체가 특정 클래스의 인스턴스인지 확인하는 연산자로, 타입에 따라 안전한 형 변환을 수행하거나 조건부 로직을 작성하는 데 유용합니다.
이 두 개념을 통해 자바에서 객체 지향 프로그래밍의 장점을 극대화하고, 코드의 안전성과 유연성을 향상시킬 수 있습니다.
카테고리 없음