[C#] 프로퍼티, 상속의 다형성

고현규·2023년 11월 7일

오늘 학습 내용

1. 프로퍼티
2. 상속의 다형성
3. 제너릭
4. out, ref


1. 프로퍼티

프로퍼티란?

  • 프로퍼티는 객체의 필드 값을 간접적으로 읽거나 설정하는데 사용되는 접근자다.
  • 외부에서 필드의 값을 접근할 수 있게 하며, 유효성 검사를 할 수 있다.
class Person
{
    private string name;
    private int age;

    public string Name
    {
        get { return name; }
        private set { name = value; }
    }

    public int Age
    {
        get { return age; }
        set
        {
            if (value >= 0)
                age = value;
        }
    }
    
    //자동 프로퍼티 
    public string Name { get; set; }
    public int Age { get; set; }
}

2. 상속과 다형성

  • 가상(Virtual) 메서드
    부모 클래스에서 정의 된것을 자식 클래스에서 재정의할 수 있는 메서드다.
public class Unit
{
    public virtual void Move()
    {
        Console.WriteLine("두발로 걷기");
    }

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

public class Marine : Unit
{

}

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

Virtual을 사용하면 "자식 클래스에서 Override 될 수 있다" 라는 의미로
자식 클래스에서 메서드를 확장한 부분을 명시해주는 역할이다.


  • 추상(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");
    }
}

이 처럼 부모 클래스에서는 명시만 되어 있고 구현은 자식 클래스에 각기 달리 되어있다.


  • Override와 Overloadingride

    • Override
      1. 자식 클래스에서 재정의 그리고 2. 똑같은 형식으로 작성

      public class Shape
      {
        	  public virtual void Draw()
        	  {
            Console.WriteLine("Drawing a shape.");
            }
        }
        
        public class Circle : Shape
        {	
      		public override void Draw()
        		{
            	Console.WriteLine("Drawing a circle.");
        		}	
      }
      
    • Overloading
      동일한 이름의 메서드지만, 매개변수가 다르다. 다양한 형식의 호출이 가능하다.

      public class Calculator
      {
      	public int Add(int a, int b)
      	{
          	return a + b;
      	}
      
      	public int Add(int a, int b, int c)
      	{
          	return a + b + c;
      	}
      }

3. 제너릭

클래스나 메서드를 일반화시켜 다양한 자료형에 대응하여 재사용률을 높인다.

class Stack<T>
{
    private T[] elements;
    private int top;

    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
//제너릭을 두개 이상 사용하는 예
class Pair<T1, T2>
{
    public T1 First { get; set; }
    public T2 Second { get; set; }

    public Pair(T1 first, T2 second)
    {
        First = first;
        Second = second;
    }

    public void Display()
    {
        Console.WriteLine($"First: {First}, Second: {Second}");
    }
}

Pair<int, string> pair1 = new Pair<int, string>(1, "One");
pair1.Display();

Pair<double, bool> pair2 = new Pair<double, bool>(3.14, true);
pair2.Display();

출력

Pair<int, string> pair1 = new Pair<int, string>(1, "One");
pair1.Display();

Pair<double, bool> pair2 = new Pair<double, bool>(3.14, true);
pair2.Display();

변수 타입 Var를 사용하는 것과 비슷하다는 생각이 들었고
Override와 비슷하게 여러 자료형으로 대응 할 수 있을 것 같다.

클래스 Stack을<T>형으로 선언하고
사용할 때 new Stack<int> 로 적으면 Stack 클래스를 int형으로 사용 가능하다.

4. 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

out, ref 주의 사항!

  1. 값의 변경 가능성
    변수의 값을 직접 변경할 수 있어 예기치 않은 동작을 초래할 수 있다.
  2. 성능 이슈
    값의 복사 없이 메서드 내에서 직접 접근하기 때문에 성능상 이점이 있다.
    하지만 너무 많은 매개변수를 ref로 전달하면 코드의 가독성과 유지보수가 어려울 수 있다.
  3. 변수 변경 여부 주의
    out 매개변수는 매서드 내에서 반드시 값을 할당해야한다. 따라서 out 매개변수를 전달할 때 해당 변수는 이전 값이 유지되지 않으니 주의해야 한다.

    느낀 점

    out, ref는 매개변수들을 사라지는 전달요소가 아니라 메인에 사용되는 변수들을 변경하는 요소로도 함께 쓰이는 것으로 보인다.
    Out은 return값을 여러개 반환하여 바로 저장하는 것처럼 사용하는 느낌이 든다.
    ref는 직접 저장된 위치를 매개변수로 전달하여 저장공간을 절약할 수 있는 점이 인상깊었다.
profile
게임 개발과 기획

0개의 댓글