가상메소드 그리고 프로퍼티
가상메소드
C++나 C#에서는 상위 클래스 형의 변수에 하위 클래스 객체의 참조를 저장할 수 있다. 컴파일 시에 변수의 형에 의해 수행될 메소드가 결정된다. 즉, 아래의 예제 코드에서 첫 번째 f의 호출도 BaseClass에 정의된 f 메소드를 나타내면 두 번째 f의 호출도 BaseClass에 정의된 f 메소드를 나타낸다. 두 번째 f의 호출 시 ob1 변수에는 DerivedClass 형 객체의 참조가 저장되어 있음에도 불구하고 ob1의 BaseClass 형의 변수이기 때문에 그렇다.
using System;
class TestClass
{
static void Main()
{
BaseClass ob1;
ob1 = new BaseClass();
ob1.f();
ob1 = new DerivedClass();
ob1.f();
Console.ReadLine();
}
}
class BaseClass
{
internal void f() { Console.WriteLine("Base Class"); }
}
class DerivedClass : BaseClass
{
internal void f() { Console.WriteLine("Derived Class"); }
}
이처럼 상위 클래스 변수를 이용하여 하위 클래스의 객체를 조작할 경우, 변수에 저장된 객체의 형에 따라 메소드를 수행시키고자 하면 아래의 예제 코드처럼 상위클래스의 메소드를 virtual 키워드를 사용하여 가상함수로 선언해주고 하위클래스에서는 override 키워드를 사용하여 상위클래스의 가상함수를 재정의함을 알려 주어야 한다.
using System;
class TestClass
{
static void Main()
{
BaseClass ob1;
ob1 = new BaseClass();
ob1.f();
ob1 = new DerivedClass();
ob1.f();
Console.ReadLine();
}
}
class BaseClass
{
internal virtual void f() { Console.WriteLine("Base Class"); }
}
class DerivedClass : BaseClass
{
internal override void f() { Console.WriteLine("Derived Class"); }
}
프로퍼티 (property)
프로그래머의 입장에서 어떤 객체의 필드 (데이터 멤버)를 직접 참조하면 편한 경우 등이 있다. 이렇게 하려면 클래스 설계 시 필드를 public으로 선언하여 사용자에게 필드를 노출하여야 한다. 그러나 사용자에게 필드를 직접 노출하게 되면 클래스 수정 시 유지 보수에 문제가 있다. 사용자에게는 필드처럼 보이지만 실제로는 필드를 참조 및 변경하는 멤버함수에 의해 동작되는 기능이 있으면 이러한 문제를 해결할 수 있을 것이다. 바로 이러한 기능을 제공해주는 것이 프로퍼티이다.
프로퍼티는 필드의 값을 얻고 설정하는 get과 set 접근자 (accessor)라고 불리는 코드 블록과 프로퍼티 선언으로 구성된다. 필요에 따라 get 접근자와 set 접근자 중 하나만 제공할 수도 있다. 아래의 예제에서는 private 필드인 length의 값을 읽고 설정하는 Length 프로퍼티를 정의하였다. get 접근자에서는 단순히 필드의 값을 리턴하도록 되어 있으며 set 접근자에서는 필드의 값을 프로퍼티에 저장하고자 하는 값 (value로 표현됨)으로 설정하도록 되어 있다.
class MyClass {
private int length;
public int Length {
get { return length; }
set { length = value; }
}
}
프로퍼티를 사용하는 방법은 마치 필드를 직접 참조하는 것처럼 하면 된다.
MyClass MyObject = new MyClass
MyObject.Length = 10;
int Length = MyObject.Length
프로퍼티는 메소드처럼 virtual, override, abstarct와 같은 접근 제한자를 이용해서 선언할 수 있으며 정적 프로퍼티도 선언할 수 있다. 정적 프로퍼티는 정적 메소드와 마찬가지로 클래스의 일반 필드들을 참조할 수 없다.
기본적으로 접근자의 액세스 수준은 이 접근자가 속한 속성의 경우와 동일하다. 그러나 때로는 이러한 접근자 중 하나에 대한 액세스를 제한해야 할 수도 있다. 이러한 기능은 C# 2.0에서부터 제공된다. 접근자에 대한 액세스 수준은 속성의 액세스 수준보다 더 제한적이어야 한다. 또한, 접근 한정자는 속성에 set 및 get 접근자가 모두 있는 경우에만 사용할 수 있으며 이 경우 한정자는 두 접근자 중 하나에 대해서만 허용된다.
public string Something
{
get { return something; }
protected set { something = value; }
}