<클래스 편>
shakeJ
참조 문서 : 가메 출판사, 김상형 저, 닷넷 프로그래밍 저, Chapter5~6, 2008년출판
! 클래스(Class)
1.1 클래스 선언
간단하게 말해서 " 변수와 함수의 집합 " "실세계의 사물"
변수는, 사물의 속성이나 상태를 표현
함수는, 사물의 동작이나 행동을 기술
클래스는 '상태'와 '동작'을 하나로 묶은, 즉 변수와 함수를 합친 것이다.
이 클래스에 속한 함수를 메소드(Method)라고 부른다.
예를 들어,
사람 (사물) 의 피부색, 나이, 성별 (상태) 와 생각한다. 공부한다. 말한다. 걷는다 (행동)이라 생각하면, 변수 함수라고 쉽게 이해를 하면 된다.
++ 추상화 -> 사물들이 가지는 이런 특성들을 잘 정리해 '필드'와 '메서드'로 표현하는 과정.
캡슐화 -> 추상화된 결과를 하나의 클래스에 포함시키고 외부에서 함부로 변경해서는 안 되는 것을 적당히 숨겨 스스로 방어하는 것을 캡슐화 라고 한다.
다형성 -> 상속을 통해 계층을 구성하며 발휘하는 특성
지정자 class 이름 : 기반클래스 { // 멤버 등록 } |
클래스에 포함되는 것들을 통틀어서 멤버라고 부른다.
이름을 표현하는 Name은 문자열 타입의 필드로 선언 – Public string
나이를 표현하는 Age는 정수로 선언 – Public int
New연산자는 메모리에 클래스 객체를 생성하며 그 참조자를 리턴한다.
Kim 을 참조자를 받음으로써 힙에 생성된 객체를 가르키도록 한다.
Human kim선언 new Human( )
Name/ Age |
Kim |
스택 참조관계 힙
다른 소스 파일에 존재하더라도 호출이 가능함.
A.cs -> B.cs 에서도 호출이 가능.
C#이 분할 선언을 지원하는 이유는 효율적인 자동화을 위해서이다.
이런 분할선언을 하는 이유는 프로그램이 복잡해지면서 (GUI 툴을 사용함으로써) 마법사 도구가 만든 코드와 사용자가 만든 코드가 섞이면 복잡해 질 뿐 더러 서로 상호간섭에 의해 엉망이 될 확률이 높기때문이다.
Form1.cs / Form1.Designer.cs
사용자는 Form1.Designer.cs을 툴로 수정하면 되고, 이 수정된 내용들은 자동적으로 Form1.cs에 변경이 되게 된다. 이 때 사용자는 툴로 수정만 하면 될 뿐, 이 툴에 대한 소스는 몰라도 된다.
분할선언 시 주의사항(본 Code는 오류 사항 예제)
//sealed지정은 한번만 하면 된다. ? sealed지정 ? 기반 클래스로 사용할수
//Interface는 달라도 병합가능. 없는 봉인클래스
public sealed partial class Human : Aclass,Inter1
{
Pubilic int Age;
Public string Name;
}
//액세스 지정자가 public = internal 일치하지않음.
//기반 클래스가 앞의 조각가 다름. Aclass = Bclass X
internal partial class Human : BClass, Inter2
{
public int Age;
public void Intro()
{
Console.WriteLine("이름" + Name);
Console.WriteLine("나이" + Age);
}
1.3 지정자
클래스의 멤버앞에는 액세스 가능성, 값 변경 가능성, 상속 가능성, 재정의 여부 등의 성질을 결정하는 여러가지 지정자 (Modifier) 를 붙일 수 있다.
private |
클래스 내부에서만 액세스 할 수 있다 |
protected |
클래스 내부 또는 파생된 클래스에서만 사용이 가능 |
public |
외부에서 마음대로 액세스가 가능 |
internal |
같은 어셈블리 내에서만 액세스 할 수 있음 ? 어셈블리란 |
protected internal |
같은 어셈블리 내에서만 또는 파생 클래스에서만 액세스 할 수 있음. |
이 때, private나 protected, public은 C++과 Java의 경우 의미가 같으며,
internal, protected internal 액세스 지정자가 더 추가되었다.
C++에서와 같은 블록의 개념이 없기 때문에, (블록의 개념?)
모든 멤버에는 일일이 액세스 지정자를 붙여야 한다.
C#에서는 액세스 지정자가 생략된 멤버에 대해서는 private가 적용되어 숨겨진다.
클래스는 액세스 지정자를 통해 중요한 멤버를 안전하게 숨김으로써 스스로의 안정성을 확보하며
숨겨진 부분에 대해서는 자유롭게 업그레이드 할 수 있다. -> 정보 은폐
((Private지정자를 통해 외부에선 알수 없고, 프로그래머는 툴을 이용하여 수정이 가능))
지정자 |
대상 |
설명 |
static |
필드,메서드,클래스 |
클래스에 소속되는 정적멤버 |
readonly |
필드 |
초기화 가능한 읽기 전용 멤버 |
const |
상수 |
읽기 전용멤버 |
virtual |
메서드 |
가상 메서드 |
override |
메서드 |
재정의된 메서드 |
new |
메서드,필드 |
부모의 메서드를 숨기는 새 메서드 |
abstract |
클래스, |
실제 구현의 가지지 않은 추상 클래스 |
sealed |
클래스,메서드 |
기반 클래스로 사용할 수 없는 봉인 클래스 |
volatile |
필드 |
최적화를 하지 않는 필드 |
extern |
메서드 |
외부에 정의된 메서드 |
때로는 하나의 멤버에 여러 개의 지정자가 필요한 경우도 있는데 이때 지정자끼리의 순서는 아무래도 상관없다.
public static int Age;
static public int Age;
1.4 생성자
생성자가 필요한 이유는, 객체 생성 시에 자동으로 호출되는 특별한 메서드이며 객체를 초기화하는 역할을 한다. 중요 필드를 숨기더라도 생성자는 객체 내부의 메서드이므로 숨겨진 멤버를 액세스 할 수 있으며 생성과 동시에 객체를 유효한 상태로 초기화하여 객체를 곧바로 사용할 수 있게 만든다. 예를 들면. Public Human(string aName, int aAge) <~ 생성자
Name, Age 필드는 private 액세스 지정자를 붙여 밖에서 액세스를 할 수 없도록 했음
(명시하지 않아도 기본적으로 private 로 표현되지만 명시를 해주는 것이 좋음)
Intro() 메서드는 외부에서 호출해야 하므로 여전히 public이다.
여기서 Main()에서 Kim과 Lee란 필드에 각 각 정보가 들어가 있다.
이때 Human 클래스에 있는 생성자에 맞는 ( , ) 형식에 있는 Main에서 불러온다.
Main에서 new연산자로 Human 객체를 생성, 생성자로 전달할 인수를 괄호안에 적음.
this(aName)은 코드의 중복을 방지하기 위해 생성자끼리 서로를 호출할 수 있는데 본체코드 이전에 이 것을 적어 필요한 생성자를 호출하면 된다.
1.5 파괴자
파괴자는 생성자의 반대되는 메서드이다.
생성자는 객체가 동작하기 위한 초기화를 수행
파괴자는 객체가 사라질 때 정리 작업을 수행
생성자와 파괴자는 둘다 명시적으로 호출할 수 없으며 닷넷 프레임워크에 의해 자동으로 호출된다는 점에서 공통적이지만 하는 동작은 정반대이다! (설명은 뒤쪽에)
파괴자의 이름은 클래스 이름 앞에 ~ 를 붙임.
Human 클래스의 파괴자는 항상 ~Human이다.
((파괴자는 내부적으로 Finalize라는 이름의 라는 이름의 메서드로 정의.))
C#에서는 이 파괴자를 잘 사용하지 않으며, 필요한 경우도 무척 드물다.
C++에서는 생성자에서 메모리를 할당했거나 어떤 자원을 생성했을 때 누군가가 이 자원을 정리해야 하므로 파괴자가 꼭 필요하지만/////////// C#에서는 리소스 관리가 가비지 컬렉터에 의해 자동화 되어 있으므로 객체가 굳이 자신이 사용하던 자원을 해제할 필요가 없다.
BuT!
필요한 상황은 프레임워크에 의해 관리되지않은 리소스를 할당했거나 가비지 컬렉터가 해제할 수 없는 자원을 사용했을 때이다!
ex> 파일을 열어 놓았다거나 네트워크 연결을 해놨다면,
화면 해상도나 사운드 카드의 볼륨처럼 메모리와 직접적인 상관이 없는 환경을 변화시켰을
때도 원래대로 복구할 때.
<다음그림 : 소켓 통신을 하는 클래스의 모형>
소켓 객체가 파괴 될 때는 더 이상 연결을 유지할 필요가 없으므로 더 이상 연결을 해제해야하는데, 가비지 컬렉터가 수행할 수 없다.
*가비지 컬렉터는 메모리 회수를 하는 것이지 객체가 실제 무슨동작 했는지는 모르기에!
*가비지 컬렉터는 한가할 때마다 쓰레기 수집을 하므로 언제 동작할지 예측 X
대개의 경우는 바로바로 해제되겠지만 시스템이 무척 바쁘다면 그렇지 않을 수도 있다.
리소스 관리가 자동으로 수행되지만, 반응이 느림.
2.클래스의 멤버
2.1 정적 멤버
클래스와 객체는 다른 것.
클래스-> 객체를 만들기 위한 형틀
객체-> 클래스가 메모리에 구현되어 생성된 실체
메모리에 구현된 클래스의 실체 -> 인스턴스
Kim 객체 Name / Age
Lee 객체 Name / Age
각 객체에서 호출하여
void Intro() { } |
객체끼리 필드는 각자 따로 가지고 메서드는 공유하게 된다.
이 경우 객체 별로 할당되는 필드, 누가 호출 하는지 구분하는 메서드를
(불러올수 있는, 즉 움직일수 있는 필드 및 메서드)
인스턴트 멤버/비정적 멤버
이 반대의 경우는 static로 정의하여 필드와 메서드 모두 정적이다.
이 정적 필드는 개별 객체에 소속되지 않으며 클래스에 직접 소속된다. 객체가 아무리 많이 생겨도 정적필드는 단하나만 생성되며 객체가 전혀 없어도 하나는 생성된다.
메모리에 딱 한번만 구성되며 모든 객체가 공유한다. 그러므로 정적필드의 값을 변경하면 같은 클래스에 속한 모든 것이 이 변경의 영향을 받는다.
정적 메서드도 클래스에 똑같이 소속되며 개별 객체에 대한 동작이 아닌 클래스 차원의 동작을 처리한다. 특정객체에 대한 처리를 하는 것이 아니므로 호출하는 객체 참조자 this필요없음.
때문에 클래스 소속의 정적 필드만 액세스 할 수 있음.
생성자에도 static 지정자를 쓸 수 있는데 정적 생성자는 정적 필드만 초기화하는 특별한 생성자이다.
Human() // 디폴트 생성자(기본이니깐 private)
static Human() //정적 생산자.
정적 생성자ㅏ는 사용자가 명시적으로 호출하지 않아도 클래스가 로드 될 때 딱 한번만 자동으로 호출.
이에 비해 인스턴스 생성자는 객체가 생성될 때마다 호출.
2.2 상수 멤버
상수 멤버는 한 번 초기화 되면 더 이상 값을 변경할 수 없는 멤버.
늘 같은 값만 가지기는 하지만 클래스에 소속된다는 면에서 수치상수와는 다르다.
const상수는 컴파일 할 때 값이 딱 한번만 초기화되며 실행중에는 절대로 변경이 불가능하다.
클래스 외부에서 상수를 참조 할때는 클래스, 상수 식으로 읽음. Date.DAY Date라는클래스의 DAY상수로 참조할수 있음.
이에 반해 readonly 는 상수이기는 하되 생성자에서 딱 한번 값을 결정할 수 있는 기회가 제공된다는 점이 const상수와 다르다.
(굳이 에를 들자면, const는 CD이고, readonly는 CD-R과같다)
'옛글 > 프로그래밍이야기' 카테고리의 다른 글
프로그래밍 이야기 - 두번째 이야기 (0) | 2010.10.28 |
---|---|
프로그래밍 이야기 - 첫번째 이야기 (0) | 2010.10.28 |
간단한 유튜브 동영상 API 받아오기 (0) | 2010.10.28 |
'UHI' 2주간의 홈페이지 제작기 (0) | 2010.10.28 |
자바를 이용한 BMI체크(비만도체크)프로그램 (0) | 2010.10.28 |