본문 바로가기
언어 정리/C# 개념 및 lib

상속과 다형성

by 알 수 없는 사용자 2024. 1. 9.

 

 

상속은 클래스가 다른 클래스의 속성과 메소드를 그대로 받아오는 것이고, 다형성은 같은 이름의 메소드가 다른 행동을 할 수 있게 하는 것이다.

 

상속을 활용하면, 코드의 재사용성을 높이고, 중복을 줄이고
다형성을 활용하면, 동일한 인터페이스에 대해 다양한 구현을 제공할 수 있어 코드의 유연성이 증가한다.
- 다형성은  주로 메소드 오버라이딩(overriding)이나 오버로딩(overloading)을 통해 구현되며, 각각 메소드 오버라이딩은 하위 클래스가 상위 클래스의 메소드를 재정의하고 오버로딩은 같은 이름의 메소드가 매개변수의 유형이나 개수에 따라 다른 동작을 하는 것을 의미한다.


상속

  - 키워드

base, this

base 는 상위 클래스 객체를 의미

this 는 해당 객체(하위클래스) 를 의미

ex)

생성자() : this()  <- 하위클래스의 다른 생성자를 호출

생성자() : base()  <- 상위 클래스의 생성자를 호출

: 오른쪽의 인자가 생성자의 파라미터로 대입 된다.

base.X 상위클래스의 X

this.Z 하위클래스의 Z

namespace practice;
using System;

public class Point
{
    public int X { get; set;}
    public int Y { get; set;}
    
    public Point(int x, int y)
    {
        X = x;
        Y = y;
    }
    // public Point(int x, int y) => (X, Y) = (x, y); // 상단과 동일한 작업 [ C# 7.0 이상에서 도입된 튜플 대입 방식 ]
}

public class Point3D : Point
{
    public int Z { get; set; }
    
    // 기존 생성자
    public Point3D(int x) : this(x, 0, 0) 
    {       // Point3D(3)
    }

    public Point3D(int x, int y) : this(x, y, 0)
    {       // Point3D(4, 5)
    }

    public Point3D(string x, string y) : this(Convert.ToInt32(x), Convert.ToInt32(y), 0)
    {       // Point3D("6", "7")
    }

    public Point3D(int x, int y, int z) : base(x, y)
    {       // Point3D(8, 9, 10)
        this.Z = z; // 하위클래스(Point3D)의 int Z 를 사용하겠다고 명시적으로 표시 this
    } 
}

class Program
{
    static void Main()
    {
        Point a = new Point(1, 2);
        Point3D b = new Point3D(3); 
        Point3D c = new Point3D(4, 5); 
        Point3D d = new Point3D("6", "7"); 
        Point3D e = new Point3D(8, 9, 10);
        
        // 결과 출력
        Console.WriteLine($"A: {a.X}, B: {a.Y}");               // 출력값 : A: 1, B: 2
        Console.WriteLine($"A: {b.X}, B: {b.Y}, Z: {b.Z}");     // 출력값 : A: 3, B: 0, Z: 0
        Console.WriteLine($"A: {c.X}, B: {c.Y}, Z: {c.Z}");     // 출력값 : A: 4, B: 5, Z: 0
        Console.WriteLine($"A: {d.X}, B: {d.Y}, Z: {d.Z}");     // 출력값 : A: 6, B: 7, Z: 0
        Console.WriteLine($"A: {e.X}, B: {e.Y}, Z: {e.Z}");     // 출력값 : A: 8, B: 9, Z: 10
    }
}

 

 


 

다형성

 

상위 클래스의 멤버함수인 Draw()함수 

[ public virtual void Draw() ]  << virtual 을 꼭 붙여야 한다.

 

하위 클래스에서 상위클래스의 멤버함수를 재정의(오버라이딩) 함

[ public override void Draw() ] << 오버라이딩시 override 를 꼭 붙여 줘야한다.

 << 하위클래스에서는 상위클래스의 virtual 함수를 정의하지 않아도 된다.

 

namespace practice;
using System;

public class Shape
{
    // A few example members
    public int X { get; private set; }
    public int Y { get; private set; }
    public int Height { get; set; }
    public int Width { get; set; }

    // Virtual method
    public virtual void Draw()
    {
        Console.WriteLine("Performing base class drawing tasks");
    }
}

public class Circle : Shape
{
    public override void Draw()
    {
        // Code to draw a circle...
        Console.WriteLine("Drawing a circle");
        base.Draw();
    }
}
public class Rectangle : Shape
{
    public override void Draw()
    {
        // Code to draw a rectangle...
        Console.WriteLine("Drawing a rectangle");
        base.Draw();
    }
}
public class Triangle : Shape
{
    // 하위클래스에서는 상위클래스의 virtual 함수를 정의하지 않아도 된다.
    // public override void Draw()
    // {
    //     // Code to draw a triangle...
    //     Console.WriteLine("Drawing a triangle");
    //     base.Draw();
    // }
}

class Program
{
    static void Main()
    {
        Shape C_S = new Circle();
        Circle C_S_2 = new Circle();
        C_S.Draw();
        C_S_2.Draw();

        Console.WriteLine("-------------------------");

        var shapes = new List<Shape>
        {
            new Rectangle(),
            new Triangle(),
            new Circle()
        };
        Console.WriteLine($"-----{shapes}--------------------");

        foreach (var shape in shapes)
        {
            shape.Draw();
        }
    }
}

댓글