상속 기반 다형성 탐색
상속 기반 다형성은 파생 클래스가 기본 클래스의 동작 및 속성을 상속하는 클래스 계층 구조를 기반으로 합니다. 상속 관계를 사용하면 파생 클래스의 개체를 기본 클래스의 개체로 처리할 수 있습니다. 파생 클래스 개체를 기본 클래스 개체로 처리할 수 있으면 컴파일 시간에 특정 형식을 알지 못하고 여러 형식의 개체에서 작동하는 코드를 작성할 수 있습니다.
다음 코드 샘플에서는 C#의 상속 기반 다형성을 보여 줍니다.
// Base class
public class Animal
{
public virtual void MakeSound()
{
Console.WriteLine("The animal makes a sound.");
}
}
// Derived class Dog
public class Dog : Animal
{
public override void MakeSound()
{
Console.WriteLine("The dog barks.");
}
}
// Derived class Cat
public class Cat : Animal
{
public override void MakeSound()
{
Console.WriteLine("The cat meows.");
}
}
// Derived class Cow
public class Cow : Animal
{
public override void MakeSound()
{
Console.WriteLine("The cow moos.");
}
}
class Program
{
static void Main()
{
// Create an array of Animal objects
Animal[] animals = new Animal[3];
Animal animal1 = new Dog();
Animal animal2 = new Cat();
Animal animal3 = new Cow();
animals[0] = animal1;
animals[1] = animal2;
animals[2] = animal3;
// Demonstrate polymorphism
foreach (Animal animal in animals)
{
animal.MakeSound();
}
}
}
이 샘플 코드에서 Program 클래스는 Animal 개체의 배열을 만들고 배열 요소에 Dog, Cat및 Cow 인스턴스를 할당합니다. 배열의 각 개체에 대해 MakeSound 메서드가 호출되어 다형성을 보여 줌
MakeSound 메서드는 각 동물 유형에 대한 특정 동작을 제공하기 위해 파생 클래스에서 재정의됩니다.
기본 클래스의 개체를 파생 클래스로 캐스팅
C#에서 캐스팅은 한 형식의 개체를 다른 형식으로 변환하는 프로세스입니다. 캐스팅은 기본 클래스와 하나 이상의 파생 클래스가 있는 상속 계층을 사용하여 다형성을 구현할 때 자주 사용됩니다.
캐스팅에는 다음과 같은 두 가지 주요 유형이 있습니다.
암시적 캐스팅: 파생 클래스를 기본 클래스로 변환할 때 자동으로 발생합니다. 파생 클래스의 모든 인스턴스도 기본 클래스의 인스턴스이기 때문에 안전합니다.
BankAccount account = new CheckingAccount();명시적 캐스팅: 캐스트 연산자가 필요하며 기본 클래스를 파생 클래스로 변환할 때 사용됩니다. 기본 클래스의 모든 인스턴스가 파생 클래스의 인스턴스가 아니므로 항상 안전하지는 않습니다.
CheckingAccount checkingAccount = (CheckingAccount)account;
is 및 as 키워드를 사용하여 개체 캐스팅
C#에서는 is 및 as 키워드를 사용하여 개체를 캐스팅할 수 있습니다. 이러한 키워드는 개체를 다른 형식으로 캐스팅하기 전에 개체의 형식을 확인하는 안전한 방법을 제공합니다. 다음은 C#에서 개체를 캐스팅하는 몇 가지 일반적인 방법입니다.
패턴 일치와 함께
is키워드 사용:if (account is CheckingAccount checkingAccount) { // Use checkingAccount as a CheckingAccount }- 이 구문은
accountCheckingAccount형식인지 확인합니다. - 확인에 성공하면
accountCheckingAccount캐스팅하고 변수checkingAccount할당합니다. - 이 방법은 한 단계에서 형식 검사 및 캐스트를 결합하므로 간결하고 안전합니다.
- 이 구문은
is키워드를 사용한 다음 명시적 캐스팅을 수행합니다.if (account is CheckingAccount) { CheckingAccount checkingAccount = (CheckingAccount)account; // Use checkingAccount as a CheckingAccount }- 이 구문은
accountCheckingAccount형식인지 확인합니다. - 확인에 성공하면
account명시적으로CheckingAccount캐스팅하고 변수checkingAccount할당합니다. - 이 방법은 패턴 일치 구문보다 자세한 정보 표시이지만 캐스팅 프로세스를 보다 세세하게 제어할 수 있습니다.
- 이 구문은
as키워드 사용:CheckingAccount checkingAccount = account as CheckingAccount; if (checkingAccount != null) { // Use checkingAccount as a CheckingAccount }- 이 구문은
accountCheckingAccount캐스팅하고 결과를checkingAccount할당합니다. - 캐스트가 성공하면
checkingAccount캐스트 개체를 포함합니다. 그렇지 않으면 null입니다. - 이 방법은 캐스트 개체를 사용하기 전에 캐스트 결과를 확인하려는 경우에 유용합니다. 예를 들어 예외를 방지하고 오류 사례를 정상적으로 처리하려는 경우입니다.
- 이 구문은
캐스팅을 구현할 때 다음 지침을 고려합니다.
-
is패턴 일치 사용: 한 단계에서 형식 검사 및 캐스트를 결합합니다. - 명시적 캐스트와 함께
is키워드 사용: 형식 확인 및 캐스팅을 두 단계로 구분하여 캐스팅 프로세스를 보다 자세히 제어할 수 있습니다. -
as키워드 사용: null을 반환하여 정상적으로 캐스팅을 시도하고 오류를 처리합니다.
-
이러한 캐스팅 기술을 이해하는 것은 C#에서 다형성 및 상속을 사용하는 데 필수적입니다.
다형성을 구현할 때 일반적인 문제 방지
상속 기반 다형성의 목표는 다음과 같은 몇 가지 사항을 피해야 하며 몇 가지 사항을 확인해야 합니다.
봉인된 클래스와 메서드를 사용하지 마세요. 봉인된 클래스와 메서드는 상속하거나 재정의할 수 없으므로 다형성을 사용하는 기능이 제한됩니다. 클래스 또는 메서드를 봉인하는 경우 추가 확장 및 사용자 지정을 방지할 수 있습니다. 예를 들어:
public sealed class BankAccount { } // This class can't be inherited정적 메서드를 과도하게 사용하지 않습니다. 정적 메서드는 클래스의 인스턴스가 아닌 클래스 자체에 속합니다. 그들은 다형성에 참여하지 않는다는 것을 의미하는 재정의 될 수 없습니다.
public static void PrintMessage() { } // This method can't be overridden긴밀한 결합을 피하십시오. 긴밀한 결합은 시스템의 클래스 또는 구성 요소가 서로 크게 의존할 때 발생합니다. 즉, 한 클래스의 변경 내용이 다른 클래스에 직접적인 영향을 줄 수 있으므로 시스템의 유연성이 떨어지고 유지 관리가 더 어려워집니다. 꽉 결합하면 코드를 테스트, 확장 및 수정하는 데 어려움이 발생할 수 있습니다.
public class BankAccount { public void TransferFunds(SavingsAccount savingsAccount) { // Tight coupling with SavingsAccount } }좋은 이유 없이 'new' 키워드를 사용하지 마세요. 'new' 키워드는 파생 클래스의 기본 클래스 메서드를 숨기며, 이로 인해 혼동과 예기치 않은 동작이 발생할 수 있습니다. 기본 클래스 메서드를 의도적으로 숨기려는 경우에만 'new' 키워드를 사용합니다.
public class Dog : Animal { public new void MakeSound() // Hides the base class method. Better to use 'override' { Console.WriteLine("The dog barks."); } }일관된 메서드 서명을 확인합니다. 파생 클래스의 재정의된 메서드가 기본 클래스 메서드와 동일한 시그니처를 갖는지 확인합니다. 메서드 시그니처를 변경하면 메서드를 재정의하지 않고 숨깁니다.
public class Animal { public virtual void MakeSound(string sound) { Console.WriteLine("The animal makes a sound."); } } public class Dog : Animal { // Method signature doesn't match the base class public override void MakeSound() { Console.WriteLine("The dog barks."); } }
요약
C#의 상속 기반 다형성을 사용하면 파생 클래스가 기본 클래스의 동작 및 속성을 상속하는 클래스의 계층 구조를 만들 수 있습니다. 이 상속 메커니즘을 사용하면 파생 클래스의 개체를 기본 클래스의 개체로 처리할 수 있습니다. 파생 클래스 개체를 기본 클래스의 멤버로 처리하는 기능을 사용하면 컴파일 시간에 특정 형식을 모르고 여러 형식의 개체에서 작동하는 코드를 작성할 수 있습니다. 캐스팅 기술을 이해하고, 일반적인 문제를 방지하고, 모범 사례를 따르면 C# 애플리케이션에서 다형성을 효과적으로 구현할 수 있습니다.