상속

부모 클래스라 불리는 기존의 클래스를 확장하거나 재사용할 수 있는 자식 클래스라 불리는 새로운 클래스를 생성하는 것.

자식 클래스는 부모 클래스의 맴버를 상속받을 수 있으며, 부모 클래스의 기능을 확장하거나 새로운 클래스로 재정의하는 것이 가능하다. 코드를 재사용할 수 있고 계층 구조로 표현할 수 있으며 유지 보수가 증가한다.

  • 단일 상속: 부모 클래스 하나, 자식 클래스 하나
  • 다중 상속: 부모 클래스가 여러 개 (C#에서는 지원X)
  • 인터페이스 상속: 인터페이스를 상속할 때만 다중 상속 가능. 하나의 클래스와 여러 개의 인터페이스를 상속한다.
    // 부모 클래스
    public class Animal
    {
        public string Name { get; set; }
        public int Age { get; set; }

        public void Eat()
        {
            Console.WriteLine("Animal is eating.");
        }

        public void Sleep()
        {
            Console.WriteLine("Animal is sleeping.");
        }
    }

    // 자식 클래스
    public class Dog : Animal
    {
        public void Bark()
        {
            Console.WriteLine("Dog is bark.");
        }
    }

    public class Cat : Animal
    {
        public void Meow()
        {
            Console.WriteLine("Cat is meow.");
        }

        public void Sleep() // 부모 클래스인 Animal의 Sleep을 숨긴다
        {
            Console.WriteLine("Cat Sleep!");
        }
    }

    static void Main(string[] args)
    {
        Dog dog = new Dog();
        dog.Name = "Bobby";
        dog.Age = 3;

        dog.Eat();
        dog.Sleep();
        dog.Bark();

        Cat cat = new Cat();
        cat.Name = "Kkami";
        cat.Age = 10;

        cat.Eat();
        cat.Sleep();
        cat.Meow();
    }
}

 

 

다형성

같은 타입이지만 다양한 동작을 수행할 수 있는 능력

 

가상 메서드

부모 클래스에서 정의되고 자식 클래스에서 재정의된다.

virtual 키워드를 사용하여 선언되며, 자식 클래스에서 필요에 따라 재정의 될 수 있다. 이를 통해 자식 클래스에서 부모 클래스의 메서드를 변경하거나 확장 가능하다.

// 가상 메서드
public class Unit
{
    public virtual void Move() // virtual -> 자신을 상속한 자식들이 재구현 할 수 있음을 선언. 실형태가 다를 수 있음을 확인해라
    {
        Console.WriteLine("두발로 걷기");
    }

    public void Attack()
    {
        Console.WriteLine("Unit 공격");
    }
}

public class Marine : Unit
{

}

public class Zergling : Unit
{
    public override void Move() // override로 재정의
    {
        Console.WriteLine("네발로 걷기");
    }
}

// 가상 메서드 호출
// #1 참조형태와 실형태가 같을때
Marine marine = new Marine();
marine.Move();
marine.Attack();

Zergling zergling = new Zergling();
zergling.Move();
zergling.Attack();

// Unit 클래스로 관리
// #2 참조형태와 실형태가 다를때
List<Unit> list = new List<Unit>();
list.Add(new Marine());
list.Add(new Zergling());

foreach (Unit unit in list)
{
    unit.Move();
}

 

추상 클래스와 메서드

직접적으로 인스턴스를 생성할 수 없다. 주로 이걸 기점으로 만든다는 느낌으로 베이스로 사용된다.

abstract 키워드를 사용하여 선언되며, 추상 메서드는 추상 메서드를 포함할 수 있다. 선언만 하고 구현하지 않기 때문에 자식 클래스에서 반드시 구현되어야 한다.

// 추상클래스
abstract class Shape
{
    public abstract void Draw();
}

class Circle : Shape
{
    public override void Draw() // 추상 메서드를 상속 받았기 때문에 반드시 구현
    {
        Console.WriteLine("Drawing a circle");
    }
}

class Square : Shape
{
    public override void Draw()
    {
        Console.WriteLine("Drawing a square");
    }
}

class Triangle : Shape
{
    public override void Draw()
    {
        Console.WriteLine("Drawing a triangle");
    }
}

// 추상 메서드 호출
// Shape shape = new Shape(); // 인스턴스를 만들 수 없음
List<Shape> list = new List<Shape>();
list.Add(new Circle());
list.Add(new Square());
list.Add(new Triangle());

foreach (Shape shape in list)
{
    shape.Draw();
}

 

 

오버라이딩과 오버로딩

 

오버라이딩

부모 클래스에 이미 정의되어 있는 메서드를 자식이 재정의 하는 것.(덮어쓰기) 이때 메서드의 이름과 매개변수의 반환 타입이 똑같아야 한다.

부모의 클래스에 정의되어 있는 동작이 아니라 새로운 동작을 재구현 할 수 있다.

 

오버로딩

매개변수의 갯수나 타입, 순서가 다른 동일한 이름의 메서드들이 여러 개 있는 것.

함수를 읽어올 때 골라 읽어올 수 있다.

 

 

메서드

중복되는 코드를 뭉쳐놓은 하나의 블록. 코드를 재사용하거나 모듈화 할 수 있게 만들어주는 것.

  • 코드의 재사용성
  • 모듈화
  • 가독성과 유지보수성
  • 중복 제거
  • 추상화

 

메서드의 구조

[접근 제한자] [리턴 타입] [메서드 이름]([매개변수])
{
    // 메서드 실행 코드
}
  • 접근 제한자(Access Modifier): 메서드에 접근할 수 있는 범위 지정. (public, private, protected 등)
  • 리턴 타입(Return Type): 메서드가 반환하는 값의 데이터 타입 지정. (반환 값이 없을 경우 void 사용)
  • 메서드 이름(Method Name): 메서드를 호출할 때 사용하는 이름.
  • 매개변수(Parameters): 메서드에 전달되는 입력 값. 0개 이상의 매개변수를 정의할 수 있다.
  • 메서드 실행에 코드(Method Body): 중괄호({}) 안에 메서드가 수행하는 작업을 구현하는 코드 작성.

 

매개변수와 반환값

static void PrintLine()
{
    for (int i = 0; i < 10; i++)
    {
        Console.Write("=");
    }
    Console.WriteLine();
}

static void PrintLine2(int count)
{
    for (int i = 0; i < count; i++)
    {
        Console.Write("=");
    }
    Console.WriteLine();
}

static int Add(int a, int b)
{
    return a + b;
}

static void Main(string[] args)
{
    // 사용 예시
    PrintLine();
    PrintLine2(20);

    int result = Add(10, 20);
    Console.WriteLine(result);
}

 

 

오버로딩

매개변수 목록이 다중 정의된 것. 매개변수의 개수, 타입, 순서가 다르면 다른 메서드로 취급한다. 메서드의 기능이나 작업은 동일하지만 입력값에 따라 다르게 동작해야 할 때 사용된다.

 

// 오버로딩
static int AddNumbers(int a, int b)
{
    return a + b;
}

static float AddNumbers(float a, float b)
{
    return a + b;
}

static int AddNumbers(int a, int b, int c)
{
    return a + b + c;
}


static void Main(string[] args)
{
    // 오버로딩 메서드 호출
    int sum1 = AddNumbers(10, 20);  // 두 개의 정수 매개변수를 가진 메서드 호출
    float sum3 = AddNumbers(10, 20); // 두 개의 실수 매개변수를 가진 메서드 호출
    int sum2 = AddNumbers(10, 20, 30);  // 세 개의 정수 매개변수를 가진 메서드 호출

 

 

재귀 호출

메서드가 자기 자신을 호출하는 것. 호출 스택에 호출된 메서드의 정보를 순차적으로 쌓고, 메서드가 반환되면서 스택에서 순차적으로 제거되는 방식이다. 메모리 사용량이 더 크고 실행 속도가 느릴 수 있으며,  무한 루프에 빠질 수 있기 때문에 주의해야한다.

 

// 재귀 호출
static void CountDown(int n)
{
    if (n <= 0)
    {
        Console.WriteLine("Done");
    }
    else
    {
        Console.WriteLine(n);
        CountDown(n - 1);  // 자기 자신을 호출
    }
}

static void Main(string[] args)
{
    // 재귀 호출
    CountDown(5);
}

 

 

구조체

여러 개의 데이터를 묶어서 하나의 사용자 정의 형식으로 만들기 위한 방법. 값 형식(대입하거나 값을 할당할 때 복사되는 것)으로 분류되며 struct 키워드를 사용하여 선언한다.

*자세한 내용은 class와 비교하며 언급

 

 

오버로딩

메서드의 이름은 같지만 다른 매개변수를 공유한다.

즉, 메서드는 같은 이름을 공유할 수 있지만 그러기 위해서는 다른 매개변수가 필요하다.

static double Multiply (double a, double b)
{
    return a * b;
}

static void Main(string[] args)
{
    double total;

    total = Multiply(2, 3);

    Console.WriteLine(total);
}

두 개의 숫자를 곱셈하는 메서드이기 때문에 세 개의 매개변수를 넣을 수 없다.

같은 이름의 변수명으로 세 개의 매개변수를 넣어 계산하는 메서드를 만들면 사용할 수 있다.

static double Multiply (double a, double b)
{
    return a * b;
}

static double Multiply(double a, double b, double c)
{
    return a * b * c;
}

static void Main(string[] args)
{
    double total;

    total = Multiply(2, 3, 4);

    Console.WriteLine(total);
}

 

 

'C# > C#' 카테고리의 다른 글

26. 예외 처리(Exception)  (0) 2023.10.11
25. params 키워드(Params Keyword)  (0) 2023.09.28
23. 리턴(Return Keyword)  (0) 2023.09.20
22. 메서드 (Methods)  (0) 2023.09.19
21. ForEach문(Foreach Loop)  (0) 2023.09.18

+ Recent posts