1. Class 상속
우리는 일상생활 속에서 어떤 공통적인 특징을 가지고 있고 특징이 공통된다면, 그 특징을 그대로 가져와서 다른 항목을 정의하는 데 사용하고는 한다. 일상적인 많은 객체들이 이러한 계층적인 관계를 이루고 있다.
차를 예로 들면 Tesla, Hyendai, BMW, Audi 4개의 차량이 있다고 해보자. 이들의 공통적인 특징은 Car라는 것이다. 만약, 각각의 타입을 정의한다고 하면 공통적으로 이것들은 시동 켜기, 시동 끄기, 엑셀, 브레이크와 같은 행위와 시동이 들어와 있는지, 연료는 얼마나 남았는지에 대한 상태 값을 제공한다. 이런 것은 차라는 특징에서 나온 것이다.
public class Tesla
{
bool powerOn;
bool electric; // Tesla 특화 멤버 필드
public void Start(){ }
public void ShutOff(){ }
public void Accelerator(){ }
public void Brake(){ }
}
public class Hyendai
{
bool powerOn;
public void Start(){ }
public void ShutOff(){ }
public void Accelerator(){ }
public void Brake(){ }
}
상속이 없다면 공통적인 특성이 있음에도 각각의 class 마다 Method와 상태값을 정의해요 한다. 이를 상속을 이용하면 공통적인 특징을 정의하는 부모 클래스를 만들고 자식 클래스에서 부모의 기능을 물려받을 수 있다.
public class Car
{
bool powerOn;
public void Start(){ }
public void ShutOff(){ }
public void Accelerator(){ }
public void Brake(){ }
}
public class Tesla : Car
{
bool electric;
}
public class Hyendai : Car
{
}
C#에서는 콜론( : )을 이용해서 부모 클래스의 기능을 물려받을 수 있다. C#에서는 단일 상속만 가능하다. Car라는 클래스를 부모 클래스로 받았으면, 다른 클래스는 부모 클래스로 상속받을 수 없다.
2. abstract
Car라는 클래스는 단일로는 생성해도 의미가 없는 인스턴스이다. 그렇기 때문에 Car 라는 부모 클래스는 인스턴스는 생성하지 못하지만 Car가 가지고 있는 특정 Method에 대해서는 자식들이 반드시 재정의하도록 강제적으로 하고 싶을 수도 있다. 이를 위한 방법이 추상 클래스(abstract class)와 추상 메서드(abstract method)이다. 추상 메서드는 abstract 예약어가 지정되고 구현 코드가 없는 Method이다. 추상 메서드는 반드시 추상 클래스 안에서만 선언할 수 있으며, 추상 메서드를 하나라도 가지고 있으면 추상 클래스로 만들어줘야 한다는 말이다.
2.1 abstract class 특징
- 추상 메서드에는 접근 제한자로 private를 사용할 수 없다.
- new를 사용해 인스턴스로 만들 수 없다
- 추상 메서드만을 가질 수 있다.
2.2 abstract class 예제
Employee라는 class를 만들고 직원의 개인 ID 번호와 연봉을 입력 받도록 한다. 그리고 추상 메서드로는 월급을 계산하는 함수인 CalcMonthSalary를 추가했다.
abstract class Employee
{
public int EmpID { get; private set; }
public long Salary { get; set; }
public Employee(int empId, long salary)
{
EmpID = empId;
Salary = salary;
}
public abstract long CalcMonthSalary();
public virtual long CalcMonthSalary_() //일반 Method도 구현할 수 있다.
{
return this.Salary / 12;
}
}
다음으로는, Employee라는 부모 클래스를 상속받는 영업직 직원 class를 만들어보자. 영업직 직원은 incentive를 따로 지정해서 연봉에 추가해주도록 하자.
class SalesPerson : Employee
{
public double Incentive { get; set; }
public SalesPerson(int empid, long salary, double incentive):base(empid, salary)
{
this.Incentive = incentive;
}
public override long CalcMonthSalary()
{
return this.Salary / 12 + (long)(this.Salary / 12 * Incentive * 0.01);
}
}
부모 클래스를 추상 클래스로 만들었고 해당 클래스에는 추상 메서드가 구현되어 있다. 그러므로 상속받는 자식 클래스에 해당 메서드에 대한 구현이 없으면 에러가 난다.
class abstract_ex1
{
static void Main()
{
Employee emp1 = new SalesPerson(1000, 30000000, 0);
Console.WriteLine(emp1.CalcMonthSalary());
}
}
Employee는 부모 클래스이기 때문에 자동으로 Class 형변환이 되어 Employee로 만들 수 있다. 추상 클래스는 new를 할 수 없기 때문에 자식 클래스로 new를 하여 인스턴스를 생성한다.
C#에서는 단일 상속만 가능하고 했는데, 한가지가 아닌 여러 가지를 상속받아서 사용하고 싶을 때고 있을 것이다. 이럴 때 사용하는 게 인터페이스이다.
3. interface
인터페이스는 계약이라고 볼 수 있다. interface는 클래스가 아니기 때문에 다중 상속이 가능하다. 인터페이스는 추상 메서드만 0개 이상 담고 있는 추상 클래스라고 봐도 무방하다.
3.1 interface 특징
- Method만을 포함할 수 있다.
- 비어 있는 인터페이스 정의가 가능하다.
- 자식 클래스에서 구현할 때, 반드시 public 접근 제한사를 명시해야 한다. (인터페이스명을 직접 붙이면 생략 가능)
- 인터페이스명을 직접 붙이는 경우에는 반드시 인터페이스로 형변환해야 호출이 가능하다.
- C#에서는 property가 메서드로 구현되기 때문에 인터페이스에 포함 가능하다.
3.2 interface 예시
interface IFlyable
{
void Fly();
}
interface IRunnable
{
void Run();
void Stop();
}
abstract class Fly
{
public abstract void CFly();
}
2개의 인터페이스와 1개의 추상 클래스를 만들었다.
class FlyingCar : Fly, IRunnable, IFlyable
{
public override void CFly()
{
Console.WriteLine("Car Fly");
}
public void Run()
{
Console.WriteLine("Car Run");
}
public void Run()
{
Console.WriteLine("Car Run");
}
public void Stop()
{
Console.WriteLine("Car Stop");
}
}
클래스와 함께 인터페이스는 여러개를 상속받을 수 있다. 추상 클래스와 다른 점은 interface로 상속받은 함수는 override 예약어가 필요 없다.
'스마트한 개발 공부 > C#' 카테고리의 다른 글
[C#] 변수를 상수형으로 만드는 방법 : readonly와 const (0) | 2021.08.19 |
---|---|
[C#] Struct 구조체 (0) | 2021.08.19 |
[C#] Method의 Parameter 전달방식과 Shallow, Deep Copy (0) | 2021.08.17 |
[C#] 사용자 정의 함수 (Method) (0) | 2021.08.15 |
[C#] 제어문(선택문 - 연산자, if, switch && 반복문 - for, while ) (0) | 2021.08.14 |