Chapter 9-2. 기타문법 : Interface(인터페이스) + 다중 상속이 가능한 이유
Categories: C Sharp
Tags: C Sharp Programming
인프런에 있는 Rookiss님의 강의 Part1: C# 기초 프로그래밍 입문 를 듣고 정리한 필기입니다. 😀
👩🏼 추상 클래스
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()
을 상속 받아야 하는지 알 수 없다.- 죽음의 다이아몬드 문제 👉 그대로 상속 받아 쓰려고 할 때, 두 부모가 동일한 함수이나 오버라이딩으로 구현부가 다른 함수를 가지고 있기 때문에 오버라이딩 하지 않고 그대로 물려 받아 사용하려고 할 때 어떤 것을 사용해야할지 애매해지는 문제
- 부모인
- 👉 이 경우 문제 발생 !!
- 1️⃣
👱♀️ 인터페이스
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() { } }
- 👉 그래서 인터페이스를 다중 상속할 수 있다. 그대로 물려주는게 하나도 없기 때문에 자식들은 무조건 오버라이딩을 해야 한다. 따라서 인터페이스를 다중 상속 받을 땐 죽음의 다이아몬드 문제가 발생하지 않는다. (선택지를 1️⃣로만 강제함)
- 즉 정말 인터페이스의 역할만 하는 것이다.
- 추상 클래스와 마찬가지로 인터페이스 타입의 객체는 생성할 수 없지만 인터페이스 타입의 변수를 선언하여 자식 타입의 객체를 업캐스팅 할 수는 있다. 👉 다형성
- 아래
flyable.Fly();
이 코드 한줄은,flyable
이 어떤 자식 타입인지에 따라 각각 다르게 실행될 것이다. 모든 자식들은 자신만의Fly()
로 재정의를 해야하기 때문이다.static void DoFly(IFlyable flyable) { flyable.Fly(); // 아무 문제 없다. } static void Main(string[] args) { IFlyable flyable = new IFlyable(); // ❌❌ 컴파일 에러 IFlyable flyable = new FlyableOrc(); // ⭕ 다형성 }
- 아래
🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄
Leave a comment