본문 바로가기

유니티 개발 정보/프로그래밍

C#의 Virtual과 Abstract 속성(Property)에 대해서

원문 보기

C# Virtaul & Abstract 속성에 대해서

최근 C#입문자들에게 C#의 Virtual과 Abstract 속성에 관한 질문을 받았다. 이에 대해서 한번 자세하게 살펴 보자.

Abstract와 Virtual 속성의 차이점

Abstract 속성은 Abstract 클래스를 만들도록 강요하지만,
Virtual 속성은 이러한 제약이 없다. Virtaul은 하위 클래스가 오버라이드(Override)를 가능하게 해준다.

Abstract 속성은 구현을 하위 클래스로 미룬다.
Virtual 속성은 기본적인 구현이 가능하다.


Virtaul 속성

Virtual 속성에 대해서 좀 더 자세하게 알아 보자.
쓰기 전용 속성(프로퍼티)을 만들기 위해서

옵션 1 : getter을 private속성으로 한다.
ex) 
public virtual string Prop1 { set; private get; }

옵션 2 : 단순히 setter만 만든다.

명시적으로 구현된 속성인 경우,
Setter만 가지는 것은 문제가 되지 않는다.

ex)
string Field;
public virtual string Prop1 { set { Field = value; } }

자동으로 구현된 속성인 경우, 반드시 getter을 가져야 한다.
왜냐하면, setter만 가질 경우, value에 접근할 방법이 없기 때문이다.
(밑에 있는 컴파일 에러를 확인해라.)

ex) 에러 발생
public virtual string Prop1 { set; }

에러:
'ConsoleApplication1.test.MyVirtaulWriteOnlyProperty1.set' must declare a body 
because it is not marked abstract or extern. Automatically implemented properties 
must define both get and set accessors.

설명:
그래서, 쓰기 전용 virtual 속성을 만들기 위해서는 반드시 명시적으로 구현된 setter을 가지고 있어야 된다.
만약 자동으로 구현된 속성을 사용중이라면, 반드시 getter와 setter을 모두 가지고 있어야 한다.


Abstract 속성

반대로, 쓰기 전용 abstract 속성은 오직 setter만 가지는 것을 가능하게 한다.
왜냐하면, abstract는 하위클래스로 구현을 미루기 때문이다.

컴파일러는 하위클래스에서 명시적으로 setter을 구현하도록 강요할 것이다.

ex)  잘못된 구현 - 1

abstract class Animal
{
     public abstract string Prop1 { set; }
}

public class Dog : Animal
{
     public override string Prop1 {set;}
}


오류:
'ConsoleApplication1.Dog.Prop1.set' must declare a body 
because it is not marked abstract or extern. 
Automatically implemented properties must define both get and set accessors.   


설명:
오류가 발생한 이유는, value값을 읽을 방법이 없기 때문이다.
그래서 컴파일러는 get, set을 모두 가지도록 강요한다.

ex) 잘못된 구현 - 2

public class Dog : Animal
{
     public override string Prop1 {get;set;}
}


에러:
'ConsoleApplication1.Dog.Prop1.get': cannot override 
because 'ConsoleApplication1.Animal.Prop1' 
does not have an overridable get accessor
    
설명:
상위 클래스에서는 getter가 정의 되어있지 않기 때문에, 하위 클래스에서 이를 정의할 수 없다.
상위 클래스의 쓰기 전용 속성을 하위클래스에서 읽기/쓰기 속성으로 변경할 수 없다.

ex) 올바르게 사용한 경우

public class Dog : Animal
{
     string field;
     public override string Prop1
     {
  
        set { field = value; }
     }
}

에러: 없음

설명:
이를 해결하기 위한 유일한 방법은, 쓰기 전용 속성을 명시적으로 쓰기 전용으로 구현하는 것이다.

이 글을 통해서 Abstract와 Virtaul에 관하여 쓰기 전용 속성을 작성하는데 이해하는데 도움이 되었기를 바란다.