[C#] Lec 08 - 프로퍼티, 인덱서
[C#] Lec 08 - 프로퍼티, 인덱서
프로퍼티(property)
프로퍼티의 존재 이유
1
2
3
4
5
6
7
8
9
10
11
12
class MyClass
{
int myField;
public int GetMyField()
{
return myField;
}
public void SetMyField(int value)
{
myField = value; // getter, setter를 따로 구현해야함.
}
}
- 위 코드 : 프로퍼티가 아닌 필드를 이용하여 getter, setter를 구현한 경우
- 필드에 은닉성을 부여하기 위해 주로 필드를 private 접근자로 제한하고 일반적으로 getter/setter 메소드를 활용함.
- public 접근자를 안쓴 필드는 모두 프로퍼티.
- 귀찮음 해소를 위해 필드 자체를 정의 하는 것을 생략하는 방법이 추가됨
- 굳이 getter method를 만들지 않게 하기 위해 value를 사용.
프로퍼티의 사용
1
2
3
4
5
6
7
8
9
10
class MyClass
{
public int MyField {
get;set;
}
public int MyField2 {
get;
}
}
- 프로퍼티 내에 필드가 정의되지 않은 것 처럼 보이지만 실제로 동작 시에는 가상의 필드를 만들어 동작함.
- getter method만을 구현할 경우 무조건 생성자에서만 set하고 Class 내부, 외부에서 모두 설정을 바꿀 수 없게 됨.
- getter setter 가 모두 구현되어 있다면 클래스 내부, 외부에서 모두 값 확인 및 변경이 가능
1
2
3
4
class Dog
{
public string Name => "asdf";
}
1
2
3
4
5
6
7
8
9
class Dog
{
string _name = "asdf";
public string Name
{
get {return _name;}
set {_name = value;}
}
}
- 위 두 코드는 완벽히 일치
프로퍼티의 초기화
- setter 메소드가 만들어 져 있는 프로퍼티의 경우에는 생성자를 만들지 않고도 인스턴스 생성과 동시에 초기화시켜줄 수 있음
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Dog
{
public int Number {
get;set;
}
public int Number2 {
get;set;
}
public int Code {
get;
}
public Dog(int a, int b) {
Number = a;
Code = b;
}
}
class Program
{
public static void Main(string[] args)
{
Dog asdf = new Dog(1,1);
Dog fdsa = new Dog() {
Number = 2, Number2=3
//, Code=3
};
}
}
- 문법에 주의 : Instance 생성할때 기본 생성자로 초기화시키려면 기본생성자()와 ; 사이에 코드블럭 만들고 프로퍼티=값, 프로퍼티는 값 입력. 여기에는 세미콜론 넣으면 안됨. 코드블럭이 끝난 뒤 ; 입력해 주어야 함.
- 당연히 set 메소드가 구현되지 않은 프로퍼티의 경우 인스턴스 생성시 초기화 못함
인터페이스와 프로퍼티
- 인터페이스에서 필드를 만들 수 없는 이유 : 인스턴스 화 즉 인터페이스를 객체로 선언할 수 없기 때문
- 인터페이스에서 프로퍼티를 만든다 -> 메서드를 만드는것과 동일한 개념이므로,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
interface IDog
{
public string Name{get;set;}
public string Color{get;}
}
class Dog : IDog
{
private string _name;
public string Name
{
get {return _name;}
set {_name = value;}
} //Interface에서 구현하라고 한 것을 구현한 모습
//Color 또한 get method를 구현해야함
}
추상 클래스와 프로퍼티
- 추상 클래스를 상속받는 이유 : 추상 메소드를 만들 수 있음. (구현이 있는 프로퍼티 + 구현이 없는 프로퍼티를 만들 수 있음)
- 추상클래스에서 구현한 추상 프로퍼티를 추상 클래스를 상속받은 클래스에서 다시 재정의해야함. (override 키워드를 이용하여)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
abstract class BaseClass
{
public int Property1 {get;set;} //구현을 가진 프로퍼티
abstract int Property2 {get ;set;} //구현이 없는 프로퍼티
}
class MyClass : BaseClass
{
public override int Property2
{
get;
set;
} // abstract class에서 abstract method로 정의된 것은 자손 클래스에서 override 키워드로 재정의해야함
}
인덱서(Indexer)
- 객체를 배열처럼 사용하기 위하여 만든 것 : 인덱서
1
2
3
4
5
6
7
8
9
10
public class MyList
{
int[] _array = new int[10];
public int this[int index]
{
get {return _array[index];}
set {_array[index] = value;}
}
}
- 인덱서를 이용하여 객체 자체를 배열처럼 이용할 수 있음
- index의 값에 의한 오류처리는 get,set 메소드 안에서 처리해줘야함
- indexer 또한 프로퍼티와 같이 객체 내부의 값에 접근하기 위한 통로 역할을 함
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class MyList
{
int[] _array = new int[10];
public int this[int index]
{
get {return _array[index];}
set
{
if (index>=_array.Length)
Array.Resize<int>(ref _array, index+1);
_array[index] = value;
}
}
public int Length {get {return _array.Length;}}
}
class Program
{
public static void Main(string[] args)
{
MyList ml = new MyList()
for (int i = 0; i<=myList.Length; i++)
{
Console.WriteLine(myList[i]);
}
}
}
IEnumerator, IEnumerable 상속
- Foreach를 넣기 위해서는 인터페이스를 상속받아야만 함
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class MyList : IEnumerable
{
int[] _array = new int[10];
public int Length { get { return _array.Length; } }
public int index { get; set; }
public int this[int index]
{
get { return _array[index]; }
set
{
if (index >= _array.Length)
Array.Resize<int>(ref _array, index + 1);
_array[index] = value;
}
}
public IEnumerator GetEnumerator()
{
for (int i = 0; i< _array.Length; i++)
{
yield return _array[i];
}
}
}
This post is licensed under CC BY 4.0 by the author.