[C#] abstract, interface, virtual
C#은 클래스, 함수 앞에 오는 키워드로 3가지가 있다
abstract, interface, virtual
- abstract(추상) : 클래스, 함수에 사용가능, 정의만 가능 오버라이드 후 구현, 1클래스 1상속
- interface(구현) : 인터페이스에 사용가능, 정의만 가능 오버라이드 후 구현, 1클래스 다중 상속(구현)
- virtual(가상) : 함수에만 사용 가능, 정의 후 구현 가능, 오버라이드 후 재구현 가능
앞서 말하자만
가상메서드는 공통점을 작성할 때 사용한다
그리고 인터페이스나 추상은 그 객체의 고유특징을 작성할 때 사용한다
또한, abstract(추상)과 interface(구현)는 반드시 상속 받은 클래스에서
재정의(오버라이드) 해야하는 특징을 가진다
virtual(가상)은 반드시 재정의 하지 않아도 되며, 하지않을 경우 부모클래스의 정의를 따른다
아래에서 천천히 설명
상속방식은 자바에선
abstract 는 extends
interface는 implments 키워드를 사용하지만
C#은 : 로 동일하다
#abstract와 virtual
Animal이라는 추상클래스에서 가상 메서드 speak1과 추상 메서드 speak2를 정의함
가상 메서드는 정의후 구현이 가능하나 추상메서드는 정의만 가능하다
이후, Dog라는 클래스에 Animal클래스를 상속시키고
추상 메서드 speak2를 재정의 후 구현하는 모습이다
가상 메서드 speak1은 재정의 하지 않으면 Animal클래스에서 구현된 내용을 따른다
#예제1 : abstract와 virtual
namespace Study
{
abstract class Animal
{
public virtual void Speak1()//정의 후 구현
{
Console.WriteLine("입력해주세요");
}
public abstract void Speak2();//정의만 가능
}
class Dog : Animal
{
public override void Speak2()//abstract는 반드시 재정의 해야하며 재정의 후 구현
{
Console.WriteLine("왈왈");
}
}
class Program
{
static void Main(string[] args)
{
Dog dog = new Dog();
dog.Speak1();//입력해주세요, Dog클래스 코드에는 보이지 않지만 자동적으로 구현이 됨
dog.Speak2();//왈왈, Dog클래스에서 재정의 후 구현
}
}
}
Dog클래스에는 speak1()메서드가 보이지 않지만 자동적으로 아래의 코드가 구현이 된 상태이다
그렇기 때문에 호출이 가능하다
여기서 base는 부모 클래스다(자바의 super와 같다)
public override void Speak1()
{
base.Speak1();
}
또한 가상메서드 speak1은 재정의 후 구현이 가능하다
#예제2 : abstract와 virtual
namespace Study
{
abstract class Animal
{
public virtual void Speak1()//정의 후 내용 작성
{
Console.WriteLine("입력해주세요");
}
public abstract void Speak2();//정의만 가능
}
class Dog : Animal
{
public override void Speak1()
{
Console.WriteLine("멍멍");
}
public override void Speak2()//abstract는 반드시 재정의 해야함
{
Console.WriteLine("왈왈");
}
}
class Program
{
static void Main(string[] args)
{
Dog dog = new Dog();
dog.Speak1();//멍멍, 가상메서드를 재정의 후 구현
dog.Speak2();//왈왈, 추상메서드를 재정의 후 구현
}
}
}
이처럼 가상메서드는 재정의 하지 않아도 부모클래스에서 구현된 코드를 따르기 때문에
공통점을 작성할 때 사용한다
예를 들면
동물이라는 부모 클래스에 "걷기", "달리기", "먹기" 같이 개, 고양이, 사슴 등이 가진 공통점은
가상 메서드로 구현후
울음소리와 같이 "멍멍", "야옹" 같은 공통되지 않는 특징은 추상 메서드로 정의만 하고
오버라이드 해서 재정의해서 사용한다
그렇기 때문에 가상메서드는 "걷기", "달리기", "먹기" 같은
공통점이기 때문에 상속받은 객체에서 일반적으로는 재정의를 하지 않는다
(만약, 걷기에 추가 기능을 넣을때만 재정의 해서 사용하는 방식
동물마다 걷기 스태미너 소모를 다르게 설정한다던지)
#interface
interface는 abstract클래스와 다르게 다중 상속이 가능하다
Test1을 보면 interface는 virtual이나 abstract 키워드가 붙어도 적용되지 않는다
virtual키워드를 사용하면 구현 자체가 되지 않으며
abstract키워드를 사용하면 무시되고 일반적인 메서드로 구현이 된다
그렇기 때문에 Test1처럼 작성하지 않고 Test2같이 작성하는 것이 일반적이다
interface Test1
{
public virtual void Eat()
{
Console.WriteLine("냠냠");
}
public abstract void Run();
}
interface Test2
{
public void Angry();
}
class Cat : Test1, Test2
{
//virtual메서드는 인식하지 않음
public void Run() //abstract메서드를 일반 메서드로 인식
{
Console.WriteLine("달린다냥");
}
public void Angry()
{
Console.WriteLine("화낸다냥");
}
}
static void Main(string[] args)
{
Cat cat = new Cat();
cat.Eat(); //에러, 인터페이스는 virtual메서드를 인식하지 않음
cat.Run();
cat.Angry();
}