C#프로그래밍 09 : 다형성

LeeWonjin·2022년 4월 20일
0

[학부]C#프로그래밍

목록 보기
9/21

정의

형식변환 수행 없이 자식클래스 메소드 호출 지원

하이딩

변수 하이딩

부모클래스에서 사용하는 변수명으로 자식클래스에 변수를 선언하는 것

new키워드를 붙여 새로 선언한다.

class Parent
{
    public int a { get; set; } = 1234;
}
class Child : Parent
{
    public new string a { get; set; } = "one-two-three-four";
}
class Program {
    static void Main(string[] args)
    {
        Child child = new Child();
        Console.WriteLine(child.a); // one-two-three-four
        Console.WriteLine(((Parent)child).a); // 1234
    }
}

메소드 하이딩

부모클래스에서 사용하는 메소드명으로 자식클래스에 메소드를 선언하는 것

new키워드를 붙여 새로 선언한다.

class Parent
{
    public void A()
    {
        Console.WriteLine("Parent");
    }
}
class Child : Parent
{
    public new void A()
    {
        Console.WriteLine("Child");
    }
}
class Program {
    static void Main(string[] args)
    {
        Child child = new Child();
        child.A(); // Child
        ((Parent)child).A(); // Parent
    }
}

메소드 오버라이드

자식 클래스에서 부모 클래스의 메소드를 재정의 하는 것. 다형성 지원을 위한 핵심 기능

특징

  • 부모클래스 메소드에 virtual, 자식클래스 메소드에 override 키워드 사용.
  • 부모/자식 클래스 메소드의 이름, 반환형, 매개변수가 모두 동일.
class Parent
{
    public virtual void Say() { Console.WriteLine("Parent"); }
}
class Child_1 : Parent
{
    public override void Say()
    {
        Console.WriteLine("Child_1");
    }
}
class Child_2 : Parent
{
    public override void Say()
    {
        Console.WriteLine("Child_2");
    }
}
class Child_3 : Parent
{
    public override void Say()
    {
        base.Say();
        Console.WriteLine("Child_3");
    }
}
class Program {
    static void Main(string[] args)
    {
        Parent[] items = new Parent[] { new Child_1(), new Child_2(), new Child_3() };
        foreach (Parent item in items)
        {
            item.Say();
            // Child_1
            // Child_2
            // Parent
            // Child_3
        }
    }
}

메소드 하이딩/오버라이딩 차이

'재정의된 메소드를 갖고있는 자식객체'를 부모클래스로 형변환하고, Say()를 호출한다.

하이딩 메소드를 갖고있는 객체는 부모클래스의 메소드를 실행한다.
오버라이딩 메소드를 갖고있는 객체는 재정의된 자신의 메소드를 실행한다.

class Parent
{
    public virtual void Say() { Console.WriteLine("Parent"); }
}
class Child_Hiding : Parent
{
    public new void Say()
    {
        Console.WriteLine("Child_Hiding");
    }
}
class Child_Overriding : Parent
{
    public override void Say()
    {
        Console.WriteLine("Child_Overriding");
    }
}
class Program {
    static void Main(string[] args)
    {
        Parent[] items = new Parent[] { new Child_Hiding(), new Child_Overriding() };
        foreach (Parent item in items)
        {
            item.Say();
            // Parent
            // Child_Overriding
        }
    }
}

sealed 키워드 (오버라이딩 제한)

오버라이드한 메소드에 sealed키워드를 사용할 수 있다.
이 메소드를 포함한 클래스를 상속한 자식은, 이 메소드를 오버라이드 할 수 없다.

class Parent {
    public virtual void A() { }
}
class Child : Parent
{
    public sealed override void A() { }
}
class ChildChild : Child
{
    // 컴파일에러
    // public override void A() { }
}

오버라이드 예시 (object 기본 메소드 확장)

Object클래스의 메소드 중 Equals(), ToString()에 대해 살펴보면, virtual메소드로 정의가 되어있다.
즉, Object를 상속하는 클래스에서 오버라이딩 할 수 있다.

public class Object {
    public virtual bool Equals() { /* .. */}
    public virtual string ToString() { /* .. */}
    // ...
}

재정의 예시

public class Gorani
{
    public string? Name { get; set; }
    public string? ID { get; set; }

    public override bool Equals(object? input)
    {
        Gorani? g = input as Gorani;
        if (g == null)
        {
            return false;
        }
        else
        {
            return Name == g.Name;
        }
    }

    public override string ToString()
    {
        return $"Name : {Name} / ID : {ID}";
    }
}

class Program
{
    static void Main(string[] args)
    {
        Gorani a = new Gorani() { Name = "a", ID = "001" };
        Gorani b = new Gorani() { Name = "b", ID = "053" };

        Console.WriteLine(a.Equals(b));
        Console.WriteLine(a.ToString());
        Console.WriteLine(b.ToString());
        Console.WriteLine(a);
        Console.WriteLine(b);
    }
}

연산자 오버로드

메소드 뿐 아니라 연산자도 오버로딩 할 수 있다.
아래와 같은 형태로 사용한다.

public static 클래스명 operator 연산자(인수){
  return 반환값;
}

아래는 + 연산자를 오버로딩한 예시이다.

public class Gorani
{
    public double noisy { get; set; }

    public static Gorani operator +(Gorani op1, Gorani op2)
    {
            return new Gorani() { noisy = op1.noisy + op2.noisy };
    }
    public override string ToString()
    {
        return noisy + "DB";
    }
}

class Program
{
    static void Main(string[] args)
    {
        Gorani a = new Gorani() { noisy = 53 };
        Gorani b = new Gorani() { noisy = 5353};

        Gorani c = a + b;
        Console.WriteLine(a + b); // 5406DB
        Console.WriteLine(c); // 5406DB
    }
}
profile
노는게 제일 좋습니다.

0개의 댓글