클래스 문법
클래스
**클래스(Class)**에는 Field, Method, 생성자, 소멸자와 같은 *멤버(Member)*를 포함할 수 있다. Filed는 클래스 내부에 선언된 속성으로 임의 형식의 변수를 말한다. 멤버를 선언할 때 접근 한정자를 생략하면 private
으로 정의된다. 객체를 생성할 때는 new
키워드를 사용하며 Reference Type으로 할당된다. 단, C#에서는 delete
와 같은 키워드가 없어서 의도적으로 할당 해제를 할 수 없다.
class Person
{
private string name; // Field
public Person() // 기본 생성자(매개변수가 없는 생성자)
{
this.name = "이름 없음"; // this 키워드를 사용하여 객체 참조
}
public Person(string name) // 매개변수가 있는 생성자
{
this.name = name;
}
~Person() // 소멸자
{
// 자원 해제
}
public void printPersonInfo() // Method
{
Console.WriteLine("Name : " + name);
}
}
클래스와 구조체 비교
특징 | 클래스 | 구조체 |
---|---|---|
형식 | Reference Type | Value Type |
할당 | Object obj = new Object(); |
Object obj; 또는 Object obj = new Object();
|
기본 생성자 정의 | 가능 | 불가능 |
상속 | 가능 | 불가능 |
인터페이스 | 가능 | 가능 |
abstract | 가능 | 가능 |
static | 가능 | 불가능 |
정적 멤버, 인스턴스 멤버
-
인스턴스 멤버 :
new
키워드를 사용해서 메모리에 할당된 객체의 멤버이다. -
정적 멤버 :
static
키워드를 사용하여 객체를 생성하지 않고도 전역으로 사용할 수 있는 멤버이다. 정적 멤버로 사용할 수 있는 멤버로는 Filed, Method, 생성자가 있다. 객체에 정적 생성자 있으면 이 생성자를 실행하기 전에 정적 멤버가 초기화되며, 정적 생성자가 없으면 정적 멤버를 처음 사용하기 전에 초기화가 된다.
class Person
{
public static int id = 0; // 정적 Filed
public static int count; // 정적 Filed
static Person() // 정적 생성자
{
count = 0;
}
public static void printICount() // 정적 Method
{
Console.WriteLine("Count : " + count);
}
}
Console.WriteLine(Person.id); // 출력 결과 : 0
Person.printICount(); // 출력 결과 : 0
Namespace
Namespace를 정의함으로써 수많은 클래스와 Method를 분류하여 쉽게 구분할 수 있도록 해준다. .NET Framework에서는 Namespace를 사용하여 **기본 클래스 라이브러리(Basic CLass Library, BCL)**를 분류해 놓았다.
namespace InputDvice
{
class Keyboard { }
}
namespace OutputDvice
{
class Monitor { }
}
InputDvice.Keyboard keyboard = new InputDvice.Keyboard();
OutputDvice.Monitor monitor = new OutputDvice.Monitor();
-
using
키워드로 Namespace를 미리 선언하면 생략해서 사용할 수 있다.
using InputDvice;
using OutputDvice;
Keyboard keyboard = new Keyboard();
Monitor monitor = new Monitor();
인터페이스
**인터페이스(Interface)**는 세부적인 내용은 구현하지 않고, 객체가 기본적으로 가져야 할 공통적인 기능들만 정의한 것이다. 정의된 기능들은 인터페이스를 상속받은 객체에서 반드시 재정의해야 하고, 그 안에서 세부적인 내용을 추가한다. 인터페이스에는 Method, Property, Event, Indexer를 멤버로 사용할 수 있다.
interface IKeyboard
{
void pressed();
}
interface IMouse
{
void click();
}
class Computer : IKeyboard, IMouse // 다중 상속 가능
{
public void pressed() { }
public void click() { }
}
인터페이스의 특징
- 기본적으로
public
과abstract
는 묵시적으로 적용된다. -
인터페이스를 상속받으면 자식 객체에서 구현할 때 반드시
public
을 사용해야 한다. - 접근 한정자(
private
,protected
,public
) 또는abstract
,virtual
,override
,new
등의 키워드를 사용할 수 없다. - 클래스는 다중 상속이 불가능하지만, 인터페이스는 다중 상속을 허용한다.
상속
**상속(Inheritance)**은 기존 클래스에서 이미 정의된 것들을 다른 클래스에서 사용하거나, 추가 또는 재정의할 수 있도록 한 것이다. 여기서 기존 클래스는 기반(Based) 클래스라고 하고, 상속받은 다른 클래스는 파생(Derived) 클래스라고 부른다. 파생 클래스는 하나의 기반 클래스만 상속 받을 수 있으며, 파생 클래스가 다른 클래스의 기반 클래스가 될 수도 있다. C#에서는 base
키워드를 사용하여 기반 클래스의 생성자나 Method를 호출할 수 있다.
class BaseClass
{
private string a;
public BaseClass(string a)
{
this.a = a;
}
}
class DerivedClass : BaseClass
{
private int b;
public void DerivedClass(string a, int age) : base(a)
{
this.b = b;
}
}
다형성
**다형성(Polymorphism)**이란 객체를 여러 형태로 가질 수 있다는 객체지향 개념 중 하나이다. Method Override, Method Overload, Abstract 클래스, 인터페이스와 같은 형태에 적용할 수 있다.
Method Override
Method Override는 기반 클래스의 Method를 파생 클래스에 적합한 Method로 재정의하는 것이다. 기반 클래스의 Method를 가상 Method로 정의하기 위해 virtual
키워드를 사용한다. 파생 클래스에서 Virtual Method와 같은 형태로 Method를 선언한 후 override
키워드를 사용하면 Method를 재정의할 수 있다.
class BaseClass
{
public virtual void printClassInfo() // Virtual Method
{
Console.WriteLine("Base Class");
}
}
class DerivedClass : BaseClass
{
public override void printClassInfo()
{
Console.WriteLine("Derived Class");
}
}
BaseClass b = new BaseClass();
BaseClass d = new DerivedClass();
b.printClassinfo(); // 출력 결과 : Base Class
d.printClassinfo(); // 출력 결과 : Derived Class
-
파생 클래스에서 Method를 재정의하지 않기 위해
override
를 사용하지 않으면, 다음과 같은 warning이 나타난다. 이때 Virtual Method를 재정의하지 않으려면new
키워드를 사용하면 된다.
현재 멤버가 해당 구현을 재정의하도록 하려면 override 키워드를 추가하십시오. 그렇지 않으면 new 키워드를 추가하십시오.
class DerivedClass : BaseClass
{
public new void printClassInfo()
{
Console.WriteLine("Derived Class");
}
}
-
Property로 정의된 Method도
override
키워드를 사용해 재정의할 수 있다.
class Item
{
private int _price;
public virtual int price
{
get { return _price; }
}
}
class UsedItem : Item
{
public override int price
{
get { return price * 0.5; }
}
}
- .Net Framework의 모든 객체는
Object
라는 기본 클래스를 상속받는다.Object
에 기본적으로 포함된 Method도 Override를 할 수 있다.
class MyClass
{
public override string ToString() // Object.ToString() Override
{
return "My Class";
}
}
Method Overload
- Method Overload는 이름만 같은 Method가 매개변수의 개수와 형식만 다르게 선언하여 다중 정의(Overloading)한 것이다.
class Mathematics
{
public int Add(int value)
{
return value;
}
public int Add(int value1, int value2)
{
return value1 + value2;
}
public double Add(double value1, double value2)
{
return value1 + value2;
}
}
Abstract 클래스
Abstract 클래스는 Abstract Method가 존재하는 클래스다. Abstract Method는 파생 클래스에서 반드시 재정의되어야 한다. Abstract 클래스의 모든 멤버가 Abstract Method로 정의되어 있으면 인터페이스와 같은 역할을 한다.
abstract class AbstractClass
{
private string _name;
public string name
{
get { return _name; }
}
public abstract void printClassInfo(); // Abstract Method
}
class MyClass : AbstractClass
{
public override void printClassInfo()
{
Console.WriteLine("My Class");
}
}
인터페이스
(이미 현재 문서에 포함된 내용)
Property
클래스에서 Field의 값을 읽거나 쓰기 위해 접근자 Method를 정의하여 사용한다. 하지만 Field를 생성할 때마다 일일이 정의하게 되면 코드가 길어져 가독성이 떨어진다. 접근자 Method 대신에 Property를 사용하면 이를 단순화 시킬 수 있다.
-
get
과set
접근자를 사용하여 Property를 사용할 수 있다.set
접근자는 매개변수 대신에value
키워드를 사용한다.
class Person
{
private string _name;
public string name
{
get { return _name; }
set { _name; = value; }
}
}
Person person;
person.age = "김선욱";
Console.WriteLine(person.name); // 출력 결과 : 김선욱
- C# 3.0부터는 자동구현 Property를 제공하여 더 간결하게 정의할 수 있다.
class Person
{
public string name { get; private set; } // 접근 한정자 사용 가능
}
Partial
Partial Type
Partial Type을 사용하여 클래스, 구조체 또는 인터페이스의 내용을 여러 개로 나누어 정의할 수 있다. 객체를 구현 할 때 역할에 따라 여러 파일로 나누어 분담할 수 있다.
// Project.model.cs
partial class Project
{
public void Model();
}
// Project.view.cs
partial class Project
{
public void View();
}
// Project.controller.cs
public partial class Project
{
public void Controller();
}