1. 클래스의 선언과 객체의 생성
클래스는 다음과 같이 class키워드를 이용해서 선언한다.
1 2 3 4 | class classname { //data and method } |
예를 한번 들어보겠습니다.
EX)
1 2 3 4 5 6 7 8 9 10 11 12 | class Car { //data public string name; public string color; //method public void enginestart() { Console.WriteLine("{0} : enginestart complete",name); } } |
이 코드의 Car 클래스에 선언되어 있는 name과 color처럼 클래스 안에 선언된 변수들을 일컬어 필드(Field)라고 한다. 그리고 필드와 메소드를 비롯하여 프로퍼티, 이벤트등의 클래스 내에 선언되어 있는 요소들을 일컬어 멤버(Member)라고 합니다.
한편, 클래스는 청사진입니다. 실체(인스턴스)가 아닙니다. 따라서 Car도 청사진이지 인스턴스가 아닙니다. 이제 Car의 인스턴스를 만들어보겠습니다.
1 2 3 4 5 | Car sonata = new Car(); sonata.color = "white"; sonata.name = "sonata"; sonata.enginestart(); Console.WriteLine("{0} : {1}, sonata.name, sonata.color); |
sonata객체를 생성할 때 다음과 같은 코드를 사용하였다.
Car sonata = new Car();
위 문장의 가장 끝에 있는 Car()는 생성자(Constructor)라고 하는 특별한 메소드이다. 생성자는 클래스의 이름과 동일한 이름을 가지며, 객체를 생성하는 역할을 해준다. Car()생성자 앞에 있는 new 키워드는 생성자를 호출해서 객체를 생성하는 데 사용하는 연산자이다. 말하자면 new 연산자와 생성자는 바늘과 실 같은 존재라고 할 수 있다.
Car클래스를 비롯한 모든 클래스는 복합 데이터 형식이다. 그리고 참조 형식이기도 하다. 다음 문장과 같은 선언문에서 sonata는 null을 가진다. sonata 자체에 메모리가 할당되는 것은 아니고 sonata는 참조로써 객체가 있는곳을 가리킬 뿐이다.
그래서 new 연산자와 생성자가 필요하다. new 연산자와 생성자를 이용해서 힙에 객체를 생성하고, sonata는 생성자가 힙에 생성한 객체를 가리킨다.
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 29 | using System; namespace ClassTest { class Car { //data public string name; public string color; //method public void enginestart() { Console.WriteLine("{0} : enginestart complete",name); } } class MainApp { static void Main(string[] args) { Car sonata = new Car(); sonata.color = "white"; sonata.name = "sonata"; sonata.enginestart(); Console.WriteLine("{0} : {1}, sonata.name, sonata.color); } } } |
2. 생성자와 소멸자
■생성자
다음은 생성자의 선언 형식이다. 보시다시피, 생성자는 클래스와 이름이 같고, 반환 형식이 없다. 생성자의 임무는 단 한가지, 해당 형식(클래스)의 객체를 생성하는 것 뿐이기 때문이다.
1 2 3 4 5 6 7 8 9 10 | class classname { 한정자 클래스이름(매개변수) { //.... } //필드 //메소드 } |
클래스를 선언할 때 명시적으로 생성자를 구현하지 않아도 컴파일러에서 생성자를 만들어준다. 컴파일러가 자동으로 만들어 주는데도 불구하고 생성자를 귀찮게 구현해야 하는 이유는 클래스의 필드 때문이다. 객체를 다루다 보면 객체를 생성하는 시점에 객체의 상태를, 다시 말해 객체의 필드를 원하는 값으로 초기화하고 싶을 때가 있다. 이 작업을 할 수 있는 최적의 장소가 바로 객체를 생성하기 위해 호출하는 메소드인 생성자이다.
다음은 생성자의 예제이다. 생성자도 여느 메소드와 마찬가지로 오버로딩이 가능하다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | class Car { public Car() { name = ""; color = ""; } public Car(string _name, string _color) { name = _name; color = _color; } public string name; public string color; //.... } |
이렇게 선언한 생성자는 다음과 같이 사용할 수 있다. 매개 변수가 없는 버전의 Car() 생성자는 컴파일러가 자동으로 생성해 준 생성자를 호출할 때처럼 사용하면 되고, 매개 변수가 있는 버전의 Car() 생성자는 생성자의 괄호안에 필요한 매개 변수를 입력하면 된다.
1 2 3 4 5 6 | Car sonata = new Car(); //Car() sonata.name = "sonata"; sonata.color = "white"; //Car(string _name, string _color) Car avante = new Car("아반떼“, ”검정색“); |
생성자는 클래스의 이름과 같다. 하지만 소멸자는 클래스 이름앞에 ∼기호를 붙이 꼴을 한다. 그리고 소멸자는 생성자와는 달리 매개 변수도 없고, 한정자도 사용하지 않는다. 또한 여러 버전의 소멸자를 만드는 오버로딩도 불가능하며 직접 호출 할 수도 없다. 소멸자의 사용법은 CLR의 가비지 컬렉터가 객체가 소멸되는 시점을 판단해서 소멸자를 호출해준다.
1 2 3 4 5 6 7 8 9 10 | class 클래스이름 { ~클래스이름() { // } //필드 //메소드 } |
소멸자는 가급적이면 사용하지 않는 것이 좋다. 왜냐하면 우리는 CLR의 가비지 컬렉터가 언제 동작할지 완벽히 예측할 수 없기 때문이다. 환경미화는 매일 같은 시간에 하지만, CLR의 가비지 컬렉터는 그렇지 않다. 치워야 할 쓰레기가 일정 양에 이르러야 동작된다. 문제는 쓰레기가 차는 시간을 정확하게 알 수 없고, 따라서 가비지 컬렉터가 동작할 시점도 알 수 없다는 것이다. 객체의 사용이 끝난 직후가 될 수도 있고 10분 후가 될 수도 있다. 중요한 자원을 소멸자에서 해제하도록 놔뒀다가는 얼마 가지 않아 자원이 금새 부족해지는 현상을 겪게 될지도 모른다.
그 뿐만 아니라 명시적으로 소멸자가 구현이 되어 있으면 가비지 컬렉터가 object로부터 상속받은 Finalize() 메소드를 클래스의 족보를 타고 올라가며 호출하기 때문에 대개의 경우 응용 프로그램 성능의 저하만 가져올 확률이 높다.
소멸자를 구현하지 말아야 할 가장 큰 이유는 바로 CLR의 가비지 컬렉터가 우리가 만든 소멸자보다 훨씬 더 똑똑하게 객체의 소멸을 처리해준다는 것이다. 그래서 생성은 생성자에게, 소멸은 가비지 컬렉터에게 맡기는 편이 좋다.
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 29 30 31 32 33 34 35 36 37 38 39 40 | using System; namespace ClassTest { class Car { public Car() { name = "" color = "" } public Car(string _name, string _color) { name = _name; color = _color; } ~Car() { Console.WriteLine("{0} : 소멸자작동!", name); } public string name; public string color; public void enginestart() { Console.WriteLine("{0} : enginestart complete", name); } } class MainApp { static void Main(string[] args) { Car sonata = new Car("sonata", "white"); sonata.enginestart(); Console.WriteLine("{0} : {1}", sonata.name, sonata.color); } } } |
'IT > C#' 카테고리의 다른 글
[C#]클래스의 이해 3-2 (0) | 2014.05.27 |
---|---|
[C#]메소드와 매개변수1-2 (0) | 2014.05.14 |
[C#]메소드와 매개변수 (0) | 2014.05.13 |