추상 클래스(abstract)
using System;
using System.Collections.Generic;
namespace CSharp
{
abstract class Monster
{
public abstract void Shout();
}
class Orc : Monster
{
public override void Shout() { Console.WriteLine("오크~~"); }
}
class Skeleton : Monster
{
public override void Shout() { Console.WriteLine("빠각~~"); }
}
class SkeletonOrc : Orc, Skeleton // ❌❌ 컴파일 에러 !
{
}
class Program
{
static void Main(string[] args)
{
Monster monster = new Monster(); // ❌❌ 컴파일 에러! 추상 클래스 타입의 객체는 만들 수 없다.
Monster monster = new Orc(); // ⭕ 다형성
}
}
}
추상 클래스의 정의
abstract class Monster
{
public abstract void Shout();
}
[추상 클래스]
추상 클래스는 abstract 추상 함수를 가지고 있는 클래스를 뜻한다.
- 추상 함수에도 abstract가 붙고, 추상 함수를 가지고 있다면 클래스 정의 앞에도 abstract를 붙여주어야 한다.
- 추상 함수 말고도 가상 함수나 일반 멤버 함수나 멤버 변수를 가질 수 있다.
- 어느 정도 구체적인 부분은 가질 수 있다는 얘기다. 👉 자식 클래스에게 물려주기 위해서
[추상 함수]
- 자식 클래스에서 반드시 오버라이딩 하도록 강제하는 함수다.
- 가상 함수처럼 업 캐스팅시 자식이 오버라이딩한 함수를 호출하도록 한다. 👉 다형성
- 가상 함수와는 달리 구현부{}를 작성하면 안된다. 함수의 인터페이스만 정의한다. 그래서 추상적으로 존재만 하는 함수라 추상 함수다!
- 오로지 구현은 자식클래스에게 맡기며 이러이러한 기능을 꼭! 꼭! 재정의 해달라는 신호와도 같다.
- 자식클래스에서 이를 오버라이딩 하지 않으면 컴파일 에러가 발생한다.
[추상 클래스 주의할 점]
1️⃣ 추상 클래스 타입의 객체 생성은 불가능하다.
Monster monster = new Monster(); // ❌❌ 컴파일 에러! 추상 클래스 타입의 객체는 만들 수 없다.
Monster monster = new Orc(); // ⭕ 다형성
추상클래스인 Monster타입의 객체를 생성할 수는 없다. 👉 컴파일 에러
- 추상 클래스엔 구현부가 없는 추상 함수가 있기 때문이다.
- 추상 클래스가 존재하는 이유는 그 자체로 객체를 만들기 위함이 아니라, 자식 클래스에게 필요한 것들을 상속해주고, 특정 추상 함수를 꼭 구현하라고 강제하기 위함이다.
다만 추상클래스 타입의 변수가 자식 클래스를 참조하는 업캐스팅은 가능하다. 👉 다형성
2️⃣ 다중 상속이 불가능하다 + 그 이유
C#에서는 추상 클래스와 그 외 평범한 일반 클래스들은 다중 상속이 불가능하다. 그 이유는 죽음의 다이아몬드 문제가 생길 수 있기 때문이다!
abstract class Monster
{
public abstract void Shout();
}
class Orc : Monster
{
public override void Shout() { Console.WriteLine("오크~~"); }
}
class Skeleton : Monster
{
public override void Shout() { Console.WriteLine("물캉~~"); }
}
class SkeletonOrc : Orc, Skeleton // ❌❌❌ 컴파일 에러 발생!
{
}
- 📜Monster
- 📜Orc
- 📜Skeleton
Orc 클래스와 Skeleton 클래스는 Monster 추상 클래스를 상속받는다.
- 따라서 Orc 클래스와 Skeleton 클래스에서는 반드시 추상 함수 Shout()를 오버라이딩 해야 한다.
SkeletonOrc 클래스에서 Orc,Skeleton 를 둘 다 상속 받으려고 한다면 (다중 상속을 받는다고 가정해본다면)
- SkeletonOrc 클래스에게 주어진 선택지는 2가지이다.
- 1️⃣ Shout()를 새롭게 오버라이딩 한다. 👉 문제 없다. 자신만의 내용으로서 새롭게 정의하는 것이기 때문에.
- 2️⃣ 부모인 Orc,Skeleton 로부터 물려받은 Shout()를 오버라이딩하지 않고 물려받은 그대로 사용한다. 👉 이 경우 문제 발생 !!
- 부모인 Orc,Skeleton 둘 다 각자 오버라이딩 해서 구현부가 다른기 때문에 두 부모 클래스의 Shout()은 서로 다른 함수나 마찬가지다. 따라서 SkeletonOrc 입장에선 어떤 Shout()을 상속 받아야 하는지 알 수 없다.
- 죽음의 다이아몬드 문제 👉 그대로 상속 받아 쓰려고 할 때, 두 부모가 동일한 함수이나 오버라이딩으로 구현부가 다른 함수를 가지고 있기 때문에 오버라이딩 하지 않고 그대로 물려 받아 사용하려고 할 때 어떤 것을 사용해야할지 애매해지는 문제
인터페이스
using System;
using System.Collections.Generic;
namespace CSharp
{
interface IFlyable
{
void Fly(); // 접근 지정자 안붙임. abstract 이런것도 안붙임
}
class FlyableOrc : Orc, IFlyable
{
public void Fly()
{
}
}
class Program
{
static void DoFly(IFlyable flyable)
{
flyable.Fly(); // 아무 문제 없다.
}
static void Main(string[] args)
{
IFlyable flyable = new FlyableOrc(); // 다형성
}
}
}
인터페이스의 정의
추상함수’만’ 가지고 있는 클래스. 추상 클래스와 달리 다중 상속이 가능하다.
- 앞에 interface 키워드를 붙여주며, class는 붙이지 않는다.
- 추상 함수는 접근 한정자 같은 어떠한 키워드도 붙지 않는다. 기본적인 함수 프로토타입만 정의한다.
- 인터페이스 이름 앞엔 I를 붙여주는게 암묵적 약속이다.
- 멤버 변수나 가상 함수나 다른 멤버 함수를 가질 수 없으며 오로지 추상 함수만 가진다. 즉 정말 인터페이스의 역할만 하는 것이다.
자식 클래스에게 이러 이러한 기능들을 꼭 너네들 방식으로 꼭꼭 구현해라! 라는 인터페이스적인 의미만 가지고 있다. 따라서 자식 클래스들에게 자신만의 구체적인 데이터를 그대로 물려주는건 단 하나도 없다. 오로지 추상함수들만 가지기 때문이다.
결론. 그래서 인터페이스를 다중 상속할 수 있다. 그대로 물려주는게 하나도 없기 때문에 자식들은 무조건 오버라이딩을 해야 한다. 따라서 인터페이스를 다중 상속 받을 땐 죽음의 다이아몬드 문제가 발생하지 않는다. (선택지를 1️⃣로만 강제함)
class FlyableOrc : Orc, IFlyable // 👉 인터페이스를 이렇게 다중 상속하는 것이 가능 !
{
public void Fly()
{
}
}
추상 클래스와 마찬가지로 인터페이스 타입의 객체는 생성할 수 없지만 인터페이스 타입의 변수를 선언하여 자식 타입의 객체를 업캐스팅 할 수는 있다. 👉 다형성
static void DoFly(IFlyable flyable)
{
flyable.Fly(); // 아무 문제 없다.
}
static void Main(string[] args)
{
IFlyable flyable = new IFlyable(); // ❌❌ 컴파일 에러
IFlyable flyable = new FlyableOrc(); // ⭕ 다형성
}
위 flyable.Fly(); 이 코드 한줄은, flyable이 어떤 자식 타입인지에 따라 각각 다르게 실행될 것이다. 모든 자식들은 자신만의 Fly()로 재정의를 해야하기 때문이다.
'공부 > 인프런 - Rookiss' 카테고리의 다른 글
Part 1-7-4. 기타 문법 : Delegate(대리자) (0) | 2023.08.03 |
---|---|
Part 1-7-3. 기타 문법 : Property(프로퍼티) (0) | 2023.08.03 |
Part 1-7-1. 기타 문법 : Generic(일반화) + object, 박싱/언박싱, where (0) | 2023.08.03 |
Part 1-6-3. 자료구조 : Dictionary (0) | 2023.08.03 |
Part 1-6-2. 자료구조 : List (0) | 2023.08.03 |