본문 바로가기

카테고리 없음

C# -생성자 /정적메서드 이어서 하기 (0531)

반응형

 

 

위의 클래스에서는 new를 통해 객체가 생성될 때 "영희" 라는 값을 생성자의 인자로 전달 받는다 이어서 생성자는 전달 받은 값을 맴버 변수인 _name에 보관해 두고 이후에 클래스의 다른 멤버 메서드에서 사용한다.

 참고로 매개변수가 하나도 없는 생성자를 기본생성자라고 해서  매개변수를 받는 다른 생성자와 구분하기도 한다 그런데 한가지 주의 할 점은 개발자가 명시적으로 생성자의 정의 한경우 컴파일러는 기본 생성자를 추가하지 않는 다는 것이다 따라서 예저의 경우 다음과 같이 객체를 생성하면 컴파일 시점에 오류가 발생한다.

Person person = new Person(); // r기본 생성자가 정의돼 있지 않아서 에러 발생

생성자를 여러개 정의 하는 것도 가능하다 예를 들어 book 클래서에 다음과 같은 생성자를 제공할 수 있다.

 

종료자 

클래스에서 생성자가 있다면 해당 객체가 제거 되는 시점에 실행될 종료자 또는 파괴자도 있을거라고 예측할 수 있다. 

생성자의 경우 사용자가 명시적으로 new를 통해 객체를 할당하는 시점에 자동으로 호출된다고 했는데 그렇다면 종료자는 언제 호출되는 걸까 제거 예약거가 없으므로 사용자가 객체를 의도적으로 제거하는 기능이 없다 상식적으로 생각해좌도 데이터를메모리에 할당만 하고 제거를 하지 않으면 언젠가는 주소 공간이 바닥이나므로 프로그램이 제대로 동작하지 않게 된다. CLR에서는 이런 문제를 내부적으로 가비지 수집기 이하 GC라고 줄여 표현 C#프로그램에서 모든 참조형 변수를 생성할 때는 GC가 관여하게 되고  GC는 요청된 변수의 타입이 요구하는 메모리르 관리 힙이라는 곳에 할당한다 또한 프로그램이 실행되고 있는 중에 GC를 스스로 적절하다고 판단되는 시점이 오면 관리 힙을 청소하는 작업을 하는데 이때 어떤 객체가 더사용되고 있지 않다면 객체의 데이터를 해제해버리단 따라서 C#의 참조형 변수가 가리키는 객체는 GC 가 호충돼야 종료자가 호출된다. 한 가지 확실한 사실은 GC가 불확실한 시점에 메모리 정리를 한다는 것이다. 종료자를 사용할 때는 정의하기에 앞서 신중하게 고민하고 판단해야한다 왜나하면 입장에서는 일반 참조 객체와는 달리 종료자가 정의된 클래스의 객체를 관리하려면 더 복잡한 과정을 거쳐야 하므로 성능면에서 부하를 줄수 있기 때문이다. 이경우 기준은 하나다 닷넷이 관리하지 않는 시스템 자원을 얻은 경우에만 종료자를 정의하라.이런 경우는 아직 한번도 없었으므로 아직까지는 종료자를  정의해아할 이유가 아무 것도 없다 그때까지는 돌료자가 단지 메서드의 특별한 유형이라는 점만 기억해두고 넘어가자 

 

정적 멤버, 인스턴스 멤버

어떤 타입을 실체화한 객체를 인스턴스라고 한다 인스턴스르 달리 표현하면 new연산자를 거쳐서 메모리에 할당된 객체라고 할 수 있다 바로 그객체와 관련된 멤버를 인스턴스 멤버라고 하며 지금까지 설명한 필드, 메서드, 생성자는 모두 여기에 속한다.  

*지금 까지 배운 필드 ,메서드, 생성자가 인스턴스 멤버라는 것을 강조하기 위해 때로는 인스턴스 필드, 인스턴스 메서드 ,인스턴스 생성자라고도 표기한다.

 

하지만 때로는 인스턴스와 관계없는 행동을 정의해야 할 때가 있다. 즉 개별 인스턴스 수준이 아닌 해당 인스턴스의 타입 전체에 걸쳐 전역적으로 적용되는 필드, 메서드 생성자가 필여할 수 있는데 ,이러한 멤버를 인스턴스 멤버와 구분해 정적 멤벌 (static member)라고 한다.

 

정적 필드

 

예를 들어 클래스의 객체가 생성될 때마다 횟수를 증가시키는 필드를 정의 한다고 해보자 인스턴스 멤버로 이런 기능을 수현할 수 있을 까 ?

-인스턴스 필드의 한계- 

 

우리가 원하는 결과는 해당 클래스에 속한 인스턴스가 생성된 총횟수를 나타내는 것으로서 위에서는 마지막 값이 2가 되기를 기대했을 것이다. 하지만 인스턴스 필드는 new로 항당받은 객체마다 고유하게 메모리를 확보하기 때문에 클래스 전역적으로 값이 유지되지 않는다 이같은 요구 사항을 만족하려면 클래스 단위의 필드를 정의해야하고 그것이 바로 정적 필드가 된다. 

 

두가지 변경 사항이 눈에 띈다 우선 필드 정의에 static 예약어가 붙었으면 클래스 밖에서 이필드를 사용할때 

클래스이름. 정적필드 형태로 접근했다 실행 결과에서 보다시피 정적 필드의 값은 new로 할당된 인스턴스와 상관 없이 존재한다 이를 돕기 위해 정적 인스턴스 필드를 각각 그림으로 표현하면 다음과 같다

 

 

 

내가 이해한것 기존에 인스턴스 멤버로는 countofinstance를 호출할때 소문자 person / class Program 안에 생성한 person 방에 Person 클래서 인스턴스 필드를 가져 온거였다 면 static 예약어가 붙은 countofinstance의 경우 방을 따로 생성 안하고 Person 클래스 명을 붙임으로써 방을 초월하는 전체를 아우르는 메서드를 생성해버린다. 

 

아진짜 ㅋㅋㅋㅋㅋ 머이래 복잡게 만들어가지고 

 

이번에는 좀더 현실적인 예를 들어 보자 정적 필드를 사용한는 전형적인 패턴 가운데 대표적으로 한가지를 꼽으라면 특정 클래스의 인스턴스를 의도적으로 단 한개만 만들고 싶은 경우다. 이 경우 캘래스 밖에서 해당 클래스의 인스턴스를 만들지 못하게끔 생성자를 private접근 제한자로 명시하고 단 하나의 인스턴스만 클래스 내부에서 미리 생성해 두는 것으로 원하는 바를 이룰  수 있다.

 

-클래스의 인스턴스를 단 하나만 만드는 예제-

 

 

 

클래스를 이렇게 정의해 두면 외부에서는 new Person 구믄은 사용할 수 없다 하지만 내부에서는 이미 정적 필드에 인스턴스를 생성해 뒀기 때문에 이후 Person.President 와 같은 방법으로만 해당 객체를 사용할 수 있다 . 

이렇게 인스턴스가 단 하나만 존재하는 타입을 특별하게 싱글턴 클래스라고 하며 이따금 단일 시스템 자원을 책임지는 타입이 필요할 때 싱글턴 클래스를 만들어 다름 클래스에 기능을 노출하는 용도로 사용한다 

 

정적 메서드 (static method)

정적 메서드는 일반 메서드에 static 예약어를 붙여서 정의 한다. 정적 메서드 역시 new로 객체를 생성하는 것과 무관하게 사용할 수 있으므로 [클래스이름].[정적메서드] 형태로 호출할 수 있다 .

 

너무 잠온다 이만 자도록하자

반응형