|
1.7.1 Constants
constant(상수)는 변하지 않는 값 - 값은 compile-time 에 산출된다 - 을 대표하는 클래스 멤버이다.
circular dependencies (상호 의존) 하지 않는 한 상수들은 같은 프로그램에서 다른 상수들에 의해 결정될 수 잇다.
class Constants
{
public const int A = 1;
public const int B = A + 1;
}
두 개의 public constants를 가진 Constants란 이름의 클래스이다.
상수는 절대 변하지 않고, 클래스를 통해서 다음과 같이 access 될 수 잇다.
class Test
{
static void Main() {
Console.WriteLine("{0}, {1}", Constants.A, Constants.B);
}
}
1.7.2 Fields(필드)
field 는 object 또는 클래스와 결합된 변수를 나타내는 멤버이다.
class Color
{
internal ushort redPart;
internal ushort bluePart;
internal ushort greenPart;
public Color(ushort red, ushort blue, ushort green) {
redPart = red;
bluePart = blue;
greenPart = green;
}
...
}
redPart, greenPart, bluePart 라는 이름의 internal 인스턴스 필드를 가진 Color 클래스 였다. 필드 또한 다음 예처럼 정적이다.
class Color
{
public static Color Red = new Color(0xFF, 0, 0);
public static Color Blue = new Color(0, 0xFF, 0);
public static Color Green = new Color(0, 0, 0xFF);
public static Color White = new Color(0xFF, 0xFF, 0xFF);
...
}
Red, Blue, Green, White 에 대한 정적인 필드 였다.
정적인 필드는 이런 시나리오에 완벽히 부합하지는 않는다. 필드는 Color 클래스가 로드될 때 초기화 되고, 이 초기화 후엔 클라이언트(client) 가 그들을 변경시키는 것을 막는 것이 아무 것도 없어진다. 그런 변경은 Color를 사용하고 그 값이 변하지 않을 것이라고 가정한 프로그램에서 예상치 못한 에러의 원인이 될 수 있다. Readonly 필드는 이런 문제들을 막는데 사용된다. readonly 필드에 대한 할당은 선언의 부분 또는 같은 클래스의 생성자 안에서 일어날 수 있다. 그래서 Color 클래스는 정적인 필드에 대해 readonly 변경자를 추가 함으로서 강화된다.
class Color
{
internal ushort redPart;
internal ushort bluePart;
internal ushort greenPart;
public Color(ushort red, ushort blue, ushort green) {
redPart = red;
bluePart = blue;
greenPart = green;
}
public static readonly Color Red = new Color(0xFF, 0, 0);
public static readonly Color Blue = new Color(0, 0xFF, 0);
public static readonly Color Green = new Color(0, 0, 0xFF);
public static readonly Color White = new Color(0xFF, 0xFF, 0xFF);
}
1.7.3 Methods (메쏘드)
method 는 object나 클래스에 의해 행해질 수 있는 계산이나 행동을 실행하는 멤버이다. Methods 는 (아마도 빈) 형식적인 인자들의 목록이나, return value (혹은 리턴값이 없을 수도 있다), 그리고 정적이거나 정적이지 않을 수도 있다. Static methods 는 클래스를 통해서 접근할 수 있다. instance methods 라 불리는 Non-static methods는 클래스의 인스턴스를 통해서 접근할 수 있다. 다음 예
using System;
public class Stack
{
public static Stack Clone(Stack s) {...}
public static Stack Flip(Stack s) {...}
public object Pop() {...}
public void Push(object o) {...}
public override string ToString() {...}
...
}
class Test
{
static void Main() {
Stack s = new Stack();
for (int i = 1; i < 10; i++)
s.Push(i);
Stack flipped = Stack.Flip(s);
Stack cloned = Stack.Clone(s);
Console.WriteLine("Original stack: " + s.ToString());
Console.WriteLine("Flipped stack: " + flipped.ToString());
Console.WriteLine("Cloned stack: " + cloned.ToString());
}
}
는 몇몇의 정적인 메쏘드(Clone and Flip) 와 몇몇의 인스턴스 메쏘드(Push, Pop, and ToString)를 가진 Stack(스택)을 보여주었다.
메쏘드는 overload(다중 의미 부여)될 수 있다. 이것은 다수의 메쏘드들이 각각 유일한 signature를 갖는 한 하나의 같은 이름을 가질 수 있다는 것을 의미한다. 메쏘드의 signature는 메쏘드의 이름과 그 수, 변경자들, 그리고 그것의 공식적인 인자들의 형에 의해 구성된다. 메쏘드의 signature는 특히 return type(반환형)을 갖지 않는다. 예를 보자.
class Test
{
static void F() {
Console.WriteLine("F()");
}
static void F(object o) {
Console.WriteLine("F(object)");
}
static void F(int value) {
Console.WriteLine("F(int)");
}
static void F(int a, int b) {
Console.WriteLine("F(int, int)");
}
static void F(int[] values) {
Console.WriteLine("F(int[])");
}
static void Main() {
F();
F(1);
F((object)1);
F(1, 2);
F(new int[] {1, 2, 3});
}
}
다수의 F 메쏘드를 갖고 이는 한 클래스를 나타내었다. 결과는 다음과 같다.
F()
F(int)
F(object)
F(int, int)
F(int[])
1.7.4 Properties(특성)
property(특성)은 object(객체)나 class(클래스)의 attribute(속성)에 대한 접근을 제공하는 멤버이다. 특성의 예로는 문자열의 길이, 글자 크기, 그리고 윈도우의 타이틀, 고객의 이름 등등. 특성은 field(필드)의 자연스러운 확장이다. 둘다 연합된 형들과 함께 멤버로 이름지어 졌고, 필드와 특성의 접근에 대한 syntax(구문론)이 같기 때문이다. 그러나 특성은 기억장소의 위치를 나타내지 않는다는 점에서 필드와 다르다. 대신에 특성은 그들의 값을 읽거나 쓰기 위해 실행하는 문장들을 구체화하는 접근자를 가지고 있다.
특성은 특성 선언자와 함께 정의된다. 특성 선언의 첫번째 부분은 필드 선언과 꽤 비슷하다. 두번째 부분은 a get accessor and/or a set accessor를 포함하는 것이다. 아래의 예에서, Button 클래스는
Caption 특성을 정의한다.
public class Button
{
private string caption;
public string Caption {
get {
return caption;
}
set {
caption = value;
Repaint();
}
}
}
특성은 get 과 set 접근자를 포함해서 위의 Caption 특성 처럼 읽거나 쓸 수 있다. get 접근자는 특성의 값이 읽혀질 때 호출되고, set 접근자는 특성의 값이 쓰여질 때 호출된다. set 접근자에서 특성에 대한 새로운 값은 value라고 명명된 함축된 인자안에서 주어진다.
특성에 대한 선언은 비교적 수월하지만 특성들의 true value는 선언 때 보단 사용시 스스로 나타난다.
Caption의 특성은 필드를 읽거나 쓸 수 있는 것과 마찬가지로 읽거나 쓸 수 있다.
Button b = new Button();
b.Caption = "ABC"; // set
string s = b.Caption; // get
b.Caption += "DEF”; // get & set
1.7.5 Events(이벤트)
event(이벤트)는 object 나 class 가 notifications(알림이나 통지)를 제공하게 하는 하나의 멤버이다. 클래스는 이벤트 선언을 하면서 하나의 이벤트를 정의한다. 이것은 필드나 특성(property) 선언과 비슷하나 이벤트 키워드를 수반한다는 점에서 다르다. 이 선언의 형은 반드시 delegate 형이어야 한다.
예제에서
public delegate void EventHandler(object sender, Event e);
public class Button
{
public event EventHandler Click;
public void Reset() {
Click = null;
}
}
이 button 클래스는 EventHandler 형의 Click 이벤트를 정의한다. 버튼 클래스 안에서, Click 멤버는 EventHander형의 private 필드에 정확히 부합한다. 하지만, 버튼 클래스 밖에서 Click 멤버는 오로지 += 와 -= 연산자들의 좌측에서 쓰인다. 이것은 Client 코드가 이벤트 핸들러에 추가 되거나 삭제 되는 것을 제제한다.
using System;
public class Form1
{
public Form1() {
//Add Button1_Click as an ebent handler for button1's Click event
Button1.Click += new EventHandler (Button1_Click);
}
Button Button1 = new Button();
void Button1_Click (object sender, Event e) {
Console.WriteLine("Button1 was clicked!");
}
public void Disconnect () {
Button1.Click -= new EventHandler (Button1_Click);
}
}
Form1 클래스를 보여준다. 이벤트 핸들러로 Button1_Click 를 집어 넣었고 Button1's Click 이벤트가 발생했다. Disconect 메쏘드로 이 이벤트 핸들러는 소멸한다.
Button 클래스는 다음 예에서 보듯이 필드 이벤트 선언 보단 특성 이벤트 선언에 사용하기 위해 다시 쓰일 수 있다.
public class Button
{
public event EventHandler Click {
get {...}
set {...}
}
public void Reset() {
Click = null;
}
}
이 변화는 Client(클라이언트) 코드에 아무런 영향을 주진 못하지만, 이는 Click 이벤트 핸들러가 하나의 필드를 반드시 나타날 필요가 없는 것과 마찬가지로 버튼 클래스가 좀더 유연한 implementation (구현)을 도와 준다