|
|
1. class
|
|
|
2. interface
|
|
|
3. Inheritance
|
|
|
4. Polymorphism
|
|
|
5. Property
|
|
|
6. generic
|
|
|
7. partial |
|
|
\ No newline at end of file |
|
|
# 1. Class
|
|
|
|
|
|
클래스는 객체지향언어에서 객체(object)의 틀을 정의하는 방법이다.
|
|
|
객체는 속성과 행동으로 이루어져 있으며, 객체의 틀을 정의하고 이를 실체화한 것을 객체 또는 인스턴스(Instance)라고 한다.
|
|
|
|
|
|
C#에서 객체의 틀은 `class` 예약어로 정의하며, `new` 연산자로 메모리를 할당하여 객체의 틀을 실체화하여 사용한다.
|
|
|
속성은 필드(Field), 행위는 메서드(Method)로 부른다.
|
|
|
|
|
|
- 인스턴스 멤버 : 실체화된 객체의 멤버(필드, 메서드)
|
|
|
- 정적(static) 필드/메서드 : 실체화된 객체의 전역 멤버(필드, 메서드)
|
|
|
- 정적(static) 생성자 : 객체가 실체화되는 시점에 단 한번만 불리는 생성자, 주로 정적 필드 초기화에 사용
|
|
|
|
|
|
```csharp
|
|
|
class Book
|
|
|
{
|
|
|
public string Title;
|
|
|
public decimal ISBN13;
|
|
|
|
|
|
public void Open()
|
|
|
{
|
|
|
Console.WriteLine("Book is opened");
|
|
|
}
|
|
|
|
|
|
public void Close()
|
|
|
{
|
|
|
Console.WriteLine("Book is closed");
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
|
|
|
# 2. Interface
|
|
|
객체지향언어에서는 클래스(또는 모듈)에 응집도(Cohesion)를 높이고 서로 간에 결합도(Coupling)을 낮추는 것이 원칙이다.
|
|
|
실제 구현에서는 클래스 상속을 최소화하거나 배제하고, 추상 클래스나 인터페이스를 사용하여 결합도를 줄이도록 권장하고 있다.
|
|
|
C#에서는 클래스 다중상속이 불가능하므로 `interface` 예약어를 이용하여 다중상속을 지원하고 있다.
|
|
|
|
|
|
|
|
|
인터페이스의 특징은 다음과 같다.
|
|
|
|
|
|
- 인터페이스 내에서는 메서드, 이벤트, 인덱서, 프로퍼티를 사용할 수 있다.
|
|
|
- 인터페이스는 필드를 포함할 수 없다.
|
|
|
- 모든 멤버는 public 접근 제한자를 기본으로 지정한다.
|
|
|
- 몸체가 정의되지 않는 추상 메서드를 멤버로 가진다.
|
|
|
- 인터페이스는 다른 인터페이스를 상속 가능하다.
|
|
|
- 클래스는 인터페이스 다중 상속할 수 있다.
|
|
|
|
|
|
```csharp
|
|
|
// 추상클래스
|
|
|
abstract class DrawingObject
|
|
|
{
|
|
|
public abstract void Draw();
|
|
|
public abstract void Move(int offset);
|
|
|
}
|
|
|
// 인터페이스
|
|
|
interface IDrawingObject
|
|
|
{
|
|
|
void Draw();
|
|
|
void Move(int offset);
|
|
|
}
|
|
|
```
|
|
|
|
|
|
|
|
|
# 3. Inheritance
|
|
|
객체지향언어에서 상속(Inheritance)은 공통적인 특징을 정의한 클래스의 기능을 물려받는 방법이다.
|
|
|
|
|
|
상속하는 클래스는 부모(parent), 기반(base), 슈퍼(super) 클래스로 불리고, 상속을 받는 클래스는 자식(child), 파생(derived), 서브(sub) 클래스로 불린다.
|
|
|
|
|
|
상속받은 클래스는 부모의 속성과 행위를 접근 제한자(Access Modifier) 규칙에 따라 접근(Access)할 수 있다.
|
|
|
|
|
|
C#은 단일 상속(Single inheritance)만 지원하며, 둘 이상의 부모 클래스로부터 다중 상속(Multiple inheritance)을 허용하지 않는다.
|
|
|
|
|
|
상속 관계에 있는 클래스 간에 부모 클래스는 자식 클래스로 형변환이 가능하지만, 자식 클래스는 부모 클래스로 형변환을 할 수 없다.
|
|
|
|
|
|
```csharp
|
|
|
public class Computer
|
|
|
{
|
|
|
bool powerOn;
|
|
|
public void Boot() { }
|
|
|
}
|
|
|
|
|
|
public class Notebook : Computer
|
|
|
{
|
|
|
bool fingerScan;
|
|
|
public bool HasFingerScanDevice() { }
|
|
|
}
|
|
|
|
|
|
public class Desktop : Computer
|
|
|
{
|
|
|
}
|
|
|
```
|
|
|
|
|
|
C#의 모든 형식(Type)은 *__object__* 클래스를 상속받았으며, 값 형식(Value type)과 참조 형식(Reference type)의 구분을 위해
|
|
|
값 형식을 가지는 모든 형식은 *__object__*의 자식 클래스인 *__System.ValueType__*을 상속받아 생성된다.
|
|
|
|
|
|
C#의 최상위 클래스인 object는 4가지 메서드를 포함하고 있다.
|
|
|
```csharp
|
|
|
public class Object
|
|
|
{
|
|
|
public virtual bool Equals(object obj); // 값을 비교한 결과를 boolean 값으로 반환
|
|
|
public virtual int GetHashCode(); // 인스턴스를 고유하게 식별할 수 있는 4바이트 int 값을 반환
|
|
|
public Type GetType(); // 해당 인스턴스의 타입 정보를 반환
|
|
|
public virtual string ToString(); // 해당 인스턴스가 속한 클래스의 전체 이름을 반환
|
|
|
}
|
|
|
```
|
|
|
|
|
|
- `sealed` : 상속을 받지 못하도록 제한하는 예약어
|
|
|
- `as` : 형변환이 가능하다면 인스턴스 값을 반환하고, 불가능하면 null을 반환하는 예약어
|
|
|
- `is` : 형변환 가능성 여부를 boolean 값으로 반환하는 예약어
|
|
|
- `typeof` : 클래스 이름으로부터 type을 반환하는 예약어
|
|
|
- `this` : 클래스 내부 코드에서 객체 자신을 가리키는 예약어
|
|
|
- `base` : 클래스 내부 코드에서 부모 클래스를 가리키는 예약어
|
|
|
|
|
|
|
|
|
# 4. Polymorphism
|
|
|
객체지향언어에서 다형성(Polymorphism)은 하나의 메소드나 클래스를 다양한 방법으로 동작시키는 것을 의미한다.
|
|
|
|
|
|
C#에서는 다형성의 구현을 메서드 오버라이드(Override)와 오버로드(Overload)를 통해 제공한다.
|
|
|
|
|
|
메서드 오버라이드는 상속관계에 있는 클래스 간에 자식클래스가 부모클래스의 메서드를 재정의(Override) 함으로써
|
|
|
각각의 객체가 다른동작을 가능하도록 하는 것이다.
|
|
|
|
|
|
자식클래스에서 재정의 할 메서드를 부모클래스에서 `virtual` 예약어를 사용하여 정의하고,
|
|
|
자식클래스는 `override` 예약어를 사용하여 정의한다.
|
|
|
|
|
|
```csharp
|
|
|
class Mammal
|
|
|
{
|
|
|
virtual public void Move();
|
|
|
}
|
|
|
|
|
|
class Lion : Mammal
|
|
|
{
|
|
|
override public void Move();
|
|
|
}
|
|
|
```
|
|
|
|
|
|
- `virtual`/`override` : 메서드 오버라이드시 사용되는 예약어
|
|
|
- `new` : 자식클래스에서 동일한 이름의 메서드가 필요할때 사용하는 예약어
|
|
|
|
|
|
|
|
|
오버로드(overload)는 크게 메서드 오버로드와 연산자 오버로드로 나뉜다.
|
|
|
|
|
|
메서드 오버로드(method overload)는 메서드의 시그니처에서 매개변수의 수, 개별 타입만을 재정의 하는 경우를 말한다.
|
|
|
|
|
|
```csharp
|
|
|
class Mathmatics
|
|
|
{
|
|
|
public int Abs(int value)
|
|
|
{
|
|
|
return (value >= 0) ? value : -value;
|
|
|
}
|
|
|
|
|
|
public double Abs(double value)
|
|
|
{
|
|
|
return (value >= 0) ? value : -value;
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
|
|
|
연산자 오버로드(Operator overload)는 해당 연산자를 사용 시 수행되는 메서드를 재정의 하는 것을 말한다.
|
|
|
|
|
|
operator 예약어와 연산자를 사용하여 메서드를 정의한다.
|
|
|
|
|
|
```csharp
|
|
|
public class Kilogram
|
|
|
{
|
|
|
public static kilogram operator +(Kilogram op1, Kilogram op2)
|
|
|
{
|
|
|
return new Kilogram(op1.mass + op2.mass);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
Kilogram kg1 = new Kilogram(5);
|
|
|
Kilogram kg2 = new Kilogram(10);
|
|
|
|
|
|
Kilogram kg3 = kg1 + kg2;
|
|
|
```
|
|
|
|
|
|
# 5. Property
|
|
|
프로퍼티는 접근자 메서드(getter)와 설정자 메서드(setter)에 대한 간편한 구문 표기방법이다.
|
|
|
|
|
|
```csharp
|
|
|
double pi = 3.14;
|
|
|
public double Pi
|
|
|
{
|
|
|
get { return pi; }
|
|
|
set { pi = value; }
|
|
|
}
|
|
|
```
|
|
|
|
|
|
# 6. generic
|
|
|
제네릭 프로그래밍에서의 제네릭(Generic)은 일반화를 의미하며, 데이터 형식에 의존하지 않고 하나의 알고리즘이 여러 데이터 타입을 지원하는 방식을 의미한다.
|
|
|
|
|
|
이러한 방식은 기존의 반복적인 코드를 대체하여 간결하고 재사용성이 높은 코드를 만드는 장점이 있으나, 가독성이 떨어지는 단점이 있다.
|
|
|
|
|
|
C#에서는 제네릭 프로그래밍의 구현을 `generic` 예약어와 `<T>`를 통해 제공한다.
|
|
|
|
|
|
```csharp
|
|
|
public class NewStack<T>
|
|
|
{
|
|
|
T[] _list;
|
|
|
public void Push(T item) { }
|
|
|
public T Pop() { }
|
|
|
}
|
|
|
```
|
|
|
|
|
|
`<T>`를 사용하여 타입을 지정할 경우 CLR의 JIT 컴파일러는 `<T>`에 대응되는 타입으로 대체하여 Native 코드를 생성한다.
|
|
|
|
|
|
따라서 형변환이 발생하지 않아 박싱/언박싱 문제가 없다.
|
|
|
|
|
|
|
|
|
# 7. partial
|
|
|
C#에서는 코드 분할을 위해 `partial` 예약어를 제공한다.
|
|
|
|
|
|
`class`, `struct`, `interface`에 사용 가능하며 메서드는 `private`으로 선언된 리턴값이 없는 메서드만 적용할 수 있다.
|
|
|
|
|
|
```csharp
|
|
|
// partical class
|
|
|
partial class Class1
|
|
|
{
|
|
|
public void Run() { }
|
|
|
}
|
|
|
|
|
|
partial class Class2
|
|
|
{
|
|
|
public void Get() { }
|
|
|
}
|
|
|
|
|
|
// partical struct
|
|
|
partial struct Struct1
|
|
|
{
|
|
|
public int ID;
|
|
|
}
|
|
|
|
|
|
partial struct Struct1
|
|
|
{
|
|
|
public string Name;
|
|
|
|
|
|
public Struct1(int id, string name)
|
|
|
{
|
|
|
this.ID = id;
|
|
|
this.Name = name;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// partical interface
|
|
|
partial interface IDoable
|
|
|
{
|
|
|
string Name { get; set; }
|
|
|
}
|
|
|
|
|
|
partial interface IDoable
|
|
|
{
|
|
|
void Do();
|
|
|
}
|
|
|
|
|
|
// IDoable 인터페이스 사용
|
|
|
public class DoClass : IDoable
|
|
|
{
|
|
|
public string Name { get; set; }
|
|
|
public void Do() { }
|
|
|
}
|
|
|
|
|
|
// partial method
|
|
|
public partial class Class1
|
|
|
{
|
|
|
public void Run()
|
|
|
{
|
|
|
DoThis();
|
|
|
}
|
|
|
|
|
|
partial void DoThis();
|
|
|
}
|
|
|
|
|
|
public partial class Class1
|
|
|
{
|
|
|
partial void DoThis()
|
|
|
{
|
|
|
Log(DateTime.Now);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
***
|
|
|
Q) string도 equals을 사용하나?
|
|
|
|
|
|
A) string에서 equals을 사용하면 참조 비교가 아닌 문자열 자체만 비교한다.
|
|
|
|
|
|
참조 비교는 ReferenceEquals 사용
|
|
|
|
|
|
일반적으로 비교연산자나 Compare 사용
|
|
|
|
|
|
http://www.simpleisbest.net/archive/2005/06/08/158.aspx
|
|
|
http://www.hoons.net/Board/cshaptip/Content/17314
|
|
|
|
|
|
Q) GetHashCode는 언제 사용하나?
|
|
|
A) 객체 참조 값 비교를 위해서 사용.
|
|
|
|
|
|
http://msdn.microsoft.com/ko-kr/library/system.object.gethashcode(v=vs.80).aspx
|
|
|
http://vsts2010.tistory.com/232
|
|
|
http://hongjinhyeon.tistory.com/59
|
|
|
|