박민혁의 개발

상속과 다형성 본문

TIL

상속과 다형성

박민혁_kog 2023. 8. 16. 15:30

상속

상속은 기존의 클래스(부모 클래스 또는 상위 클래스)를 확장하거나 재사용하여 새로운 클래스(자식 클래스 또는 하위 클래스)를 생성하는 것입니다.

 

  1. 상속의 장점:
    • 코드의 재사용성
    • 계층 구조의 표현 
    • 유지보수성의 향상 - 부모 클래스만 수정시 하위 클래스도 반영됨
  2. 상속의 특징:
    • 부모 클래스의 멤버에 접근 - 자식 클래스는 부모 클래스에 접근가능
    • 메서드 재정의 - 자식 클래스는 부모 클래스의 메서드를 재정의하여 자신에게 맞게 수정가능(다형성(Polymorphism)).
  3. 상속의 종류:
    • 단일 상속: 하나의 자식 클래스가 하나의 부모 클래스만 상속받는 것  C#에서는 단일 상속만을 지원합니다.
    • 다중 상속: 하나의 자식 클래스가 여러 개의 부모 클래스를 동시에 상속받는 것을 말합니다. C#은 다중 상속을 지원하지 않습니다.
    • 인터페이스 상속: 클래스가 인터페이스를 상속받는 것을 말합니다. 인터페이스는 다중 상속을 지원하며, 클래스는 하나의 클래스와 여러 개의 인터페이스를 동시에 상속받을 수 있습니다.
  4. 접근 제한자와 상속:
    • 상속 관계에서 멤버의 접근 제한자는 중요한 역할을 합니다. 부모 클래스의 멤버의 접근 제한자에 따라 자식 클래스에서 해당 멤버에 접근할 수 있는 범위가 결정됩니다.
    • 접근 제한자를 통해 상속된 멤버의 가시성을 조절하여 캡슐화와 정보 은닉을 구현할 수 있습니다.

EX

// 부모 클래스
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 Sleep()
    {
        Console.WriteLine("Cat is sleeping.");
    }

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

// 사용 예시
Dog dog = new Dog();
dog.Name = "Bobby";
dog.Age = 3;

dog.Eat();      // Animal is eating.
dog.Sleep();    // Animal is sleeping.
dog.Bark();     // Dog is barking

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

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

 

다형성

1. 가상(Virtual) 메서드 

  • 가상 메서드는 기본적으로 부모 클래스에서 정의되고 자식 클래스에서 재정의할 수 있는 메서드입니다.
  • 가상 메서드는 virtual 키워드를 사용하여 선언되며, 자식 클래스에서 필요에 따라 재정의될 수 있습니다.
  • 가상 메서드는 자식 클래스에서 override 키워드를 사용하여 재정의합니다.
(Virtual)

2.추상 메서드

  • 추상 클래스는 직접적으로 인스턴스를 생성할 수 없는 클래스
  • 주로 상속을 위한 베이스 클래스로 사용됩니다.
  • 추상 클래스는 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");
    }
}

오버라이딩 과 오버로딩

  • 오버라이딩(Overriding)
    • 부모 클래스에서 이미 정의된 메서드를 자식 클래스에서 재정의하는 것을 의미합니다.
    • 이는 상속 관계에 있는 클래스 간에 발생하며, 메서드의 이름, 매개변수 및 반환타입이 동일해야 합니다.
  • 오버로딩(Overloading)
    • 동일한 메서드 이름을 가지고 있지만, 매개변수의 개수, 타입 또는 순서가 다른 여러 개의 메서드를 정의하는 것을 의미합니다.
    • 오버로딩을 통해 동일한 이름을 가진 메서드를 다양한 매개변수 조합으로 호출할 수 있습니다.

제너릭

    1. 제너릭 사용법
    • 제너릭은 클래스나 메서드를 일반화시켜 다양한 자료형에 대응할 수 있는 기능입니다.
    • 제너릭을 사용하면 코드의 재사용성을 높일 수 있습니다.
    • C#에서는 <T> 형태의 키워드를 이용하여 제너릭을 선언합니다.
    • 제너릭 클래스나 메서드에서 사용할 자료형은 선언 시점이 아닌 사용 시점에 결정됩니다.
    • 제너릭 클래스나 메서드를 사용할 때는 <T> 대신 구체적인 자료형을 넣어줍니다.
// 제너릭 클래스 선언 예시
class Stack<T>
{
    private T[] elements;
    private int top;
//T 하나로 푸시(증가) 팝 (감소)를 사용
    public Stack()
    {
        elements = new T[100];
        top = 0;
    }

    public void Push(T item)
    {
        elements[top++] = item;
    }

    public T Pop()
    {
        return elements[--top];
    }
}

// 제너릭 클래스 사용 예시
Stack<int> intStack = new Stack<int>();
intStack.Push(1);
intStack.Push(2);
intStack.Push(3);
Console.WriteLine(intStack.Pop()); // 출력 결과: 3

out, ref 키워드

out, ref 키워드

    사용법

    • out, ref 키워드는 메서드에서 매개변수를 전달할 때 사용합니다.
    • out 키워드는 메서드에서 반환 값을 매개변수로 전달하는 경우에 사용합니다.
    • ref 키워드는 메서드에서 매개변수를 수정하여 원래 값에 영향을 주는 경우에 사용합니다.
    • out, ref 키워드를 사용하면 메서드에서 값을 반환하는 것이 아니라, 매개변수를 이용하여 값을 전달할 수 있습니다.
// out 키워드 사용 예시
void Divide(int a, int b, out int quotient, out int remainder)
{
    quotient = a / b;
    remainder = a % b;
}

int quotient, remainder;
Divide(7, 3, out quotient, out remainder);
Console.WriteLine($"{quotient}, {remainder}"); // 출력 결과: 2, 1

// ref 키워드 사용 예시
void Swap(ref int a, ref int b)
{
    int temp = a;
    a = b;
    b = temp;
}

int x = 1, y = 2;
Swap(ref x, ref y);
Console.WriteLine($"{x}, {y}"); // 출력 결과: 2, 1
  • 주의 사항
    1. 값의 변경 가능성: ref 매개변수를 사용하면 메서드 내에서 해당 변수의 값을 직접 변경할 수 있습니다. 이는 예기치 않은 동작을 초래할 수 있으므로 주의가 필요합니다.
    2. 성능 이슈: ref 매개변수는 값에 대한 복사 없이 메서드 내에서 직접 접근할 수 있기 때문에 성능상 이점이 있습니다. 그러나 너무 많은 매개변수를 **ref**로 전달하면 코드의 가독성이 떨어지고 유지보수가 어려워질 수 있습니다. 적절한 상황에서 **ref**를 사용하는 것이 좋습니다.
    3. 변수 변경 여부 주의: out 매개변수는 메서드 내에서 반드시 값을 할당해야 합니다. 따라서 out 매개변수를 전달할 때 해당 변수의 이전 값이 유지되지 않으므로 주의해야 합니다.

'TIL' 카테고리의 다른 글

예외처리 값형&참조형 박싱&언박싱  (0) 2023.08.16
인터페이스 , 열거형 개념  (0) 2023.08.16
클래스와 객체  (0) 2023.08.16
메서드 와 구조체  (0) 2023.08.16
자료형 배열 컬렉션 햇갈리는 부분 정리  (0) 2023.08.14