업캐스팅과 다운캐스팅
Coddy C# 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 70개 중 29번째.
상속 계층 구조를 다룰 때, 기본 타입과 파생 타입 간의 변환이 필요한 경우가 많습니다. 업캐스팅(Upcasting)은 파생 타입을 기본 타입으로 변환하는 반면, 다운캐스팅(Downcasting)은 그 반대의 작업을 수행합니다.
업캐스팅은 암시적이며 항상 안전합니다. 파생 클래스는 기본 클래스가 가진 모든 것을 가지고 있음이 보장되기 때문입니다:
Dog myDog = new Dog();
Animal animal = myDog; // 업캐스팅 - 암시적, 항상 가능함다운캐스팅은 명시적 형변환을 필요로 하며, 객체가 실제로 캐스팅하려는 타입이 아닌 경우 런타임에 실패할 수 있습니다:
Animal animal = new Dog();
Dog dog = (Dog)animal; // 다운캐스팅 - 실제로는 Dog이므로 작동합니다
Animal cat = new Cat();
Dog wrong = (Dog)cat; // InvalidCastException이 발생합니다!안전하게 다운캐스팅하려면, 먼저 is 키워드를 사용하여 타입을 확인하거나, 예외를 발생시키는 대신 null을 반환하는 as를 사용하세요:
if (animal is Dog d)
{
d.Bark(); // 안전함 - d는 검사가 통과된 경우에만 사용할 수 있음
}
Dog maybeDog = animal as Dog;
if (maybeDog != null)
{
maybeDog.Bark();
}현대적인 C#에서는 is 패턴 일치 방식이 타입 체크와 캐스팅을 한 단계로 결합하여 코드를 더 안전하고 깔끔하게 만들어 주기 때문에 선호됩니다.
챌린지
쉬움상속 계층 구조에서 업캐스팅(upcasting)과 다운캐스팅(downcasting)을 사용하여 객체를 유연하게 다루는 방법을 보여주는 차량 검사 시스템을 구축해 보겠습니다. 다양한 차량 유형을 생성하고, 특정 차량 종류를 안전하게 식별하고 상호 작용하는 코드를 작성하게 됩니다.
코드는 다음 네 개의 파일로 구성됩니다:
Vehicle.cs:Inspection네임스페이스에 기본Vehicle클래스를 정의합니다. 모든 차량은 생성자를 통해 설정되는LicensePlate속성(string)을 가집니다."Vehicle: {LicensePlate}"를 반환하는GetBasicInfo()메서드를 포함하세요.Car.cs:Inspection네임스페이스에Vehicle을 상속받는Car클래스를 정의합니다. 자동차는 추가로NumberOfDoors속성(int)을 가집니다. 생성자는 번호판과 문 개수를 모두 받습니다."{LicensePlate} honks: Beep beep!"을 반환하는Honk()메서드를 추가하세요.Motorcycle.cs:Inspection네임스페이스에Vehicle을 상속받는Motorcycle클래스를 정의합니다. 오토바이는HasSidecar속성(bool)을 가집니다. 생성자는 번호판과 사이드카 유무 상태를 받습니다."{LicensePlate} revs: Vroom!"을 반환하는Rev()메서드를 추가하세요.Program.cs: 메인 파일에서 차량을 생성하고 업캐스팅과 안전한 다운캐스팅을 연습합니다. 입력 값을 사용하여Car와Motorcycle을 생성한 다음, 두 객체를 모두Vehicle참조 배열에 저장합니다(업캐스팅). 배열을 루프하며 각 차량에 대해 기본 정보를 출력합니다. 그런 다음 패턴 매칭과 함께is키워드를 사용하여 안전하게 다운캐스팅합니다.Car인 경우Honk()를 호출하고,Motorcycle인 경우Rev()를 호출합니다.
네 개의 입력을 받게 됩니다:
- 자동차 번호판
- 문의 개수
- 오토바이 번호판
- 사이드카 유무 (
true또는false)
배열의 각 차량에 대해 다음 형식으로 출력을 인쇄하세요:
{GetBasicInfo() result}
{Honk() or Rev() result based on actual type}예를 들어, 입력이 ABC-123, 4, XYZ-789, false인 경우 출력은 다음과 같아야 합니다:
Vehicle: ABC-123
ABC-123 honks: Beep beep!
Vehicle: XYZ-789
XYZ-789 revs: Vroom!모든 차량이 Vehicle 참조로 저장되지만(업캐스팅), 다운캐스팅을 위한 is 패턴 매칭 구문을 사용하여 실제 유형을 안전하게 찾아내고 유형별 메서드에 액세스할 수 있다는 점에 주목하세요!
치트 시트
상속 계층 구조를 다룰 때, 업캐스팅(upcasting)은 파생 타입을 기본 타입으로 변환하고, 다운캐스팅(downcasting)은 기본 타입을 파생 타입으로 변환합니다.
업캐스팅은 암시적이며 항상 안전합니다:
Dog myDog = new Dog();
Animal animal = myDog; // 업캐스팅 - 암시적, 항상 작동함다운캐스팅은 명시적 캐스트가 필요하며 런타임에 실패할 수 있습니다:
Animal animal = new Dog();
Dog dog = (Dog)animal; // 다운캐스팅 - 실제 Dog이므로 작동함
Animal cat = new Cat();
Dog wrong = (Dog)cat; // InvalidCastException 발생!패턴 매칭과 함께 is 키워드를 사용하는 안전한 다운캐스팅 (권장됨):
if (animal is Dog d)
{
d.Bark(); // 안전함 - d는 체크를 통과한 경우에만 사용할 수 있음
}as 키워드를 사용하는 안전한 다운캐스팅 (캐스트 실패 시 null 반환):
Dog maybeDog = animal as Dog;
if (maybeDog != null)
{
maybeDog.Bark();
}직접 해보기
using System;
using Inspection;
class Program
{
public static void Main(string[] args)
{
// 입력 읽기
string carPlate = Console.ReadLine();
int numberOfDoors = Convert.ToInt32(Console.ReadLine());
string motorcyclePlate = Console.ReadLine();
bool hasSidecar = Convert.ToBoolean(Console.ReadLine());
// TODO: carPlate와 numberOfDoors를 사용하여 Car 객체 생성
// TODO: motorcyclePlate와 hasSidecar를 사용하여 Motorcycle 객체 생성
// TODO: 두 차량을 모두 포함하는 Vehicle 참조 배열 생성 (upcasting)
// TODO: 배열을 순회하며 각 차량에 대해 다음을 수행:
// - GetBasicInfo()의 결과 출력
// - 'is' 키워드와 패턴 매칭을 사용하여 안전하게 downcast:
// - Car인 경우, Honk()를 호출하고 출력
// - Motorcycle인 경우, Rev()를 호출하고 출력
}
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.