상속 (Inheritance) (tistory.com)
상속(Inheritance) 개념은 게임에서 정말 중요한 개념 중 하나이기 때문에 이전에 썼던 상속글에 살을 붙여 두 번째 글을 쓰겠습니다. 상속에 활용되는 여러 개념과 코드들을 다루겠습니다.
- 상속(Inheritance)
상속은 class를 다룰 때 사용하는 개념으로 부모 class가 메서드(Method)를 생성하고 자식 class에서 부모 클래스를 상속하고 그에 따라 메서드(Method)를 변환하여 사용하는 개념입니다. C#에서 부모 = Base / 자식 = Derived로 사용됩니다. 위는 weapon이라는 Base class에 Attack()이라는 메서드를 생성하고 gun, sword, bow 3개의 Derived class에서 상속받고 함수를 각자에 맞게 바꿔 사용합니다.
- 형변환
Base baseTest = derivedClass; //묵시적 형변환, (Base)derivedClass; 이건 명시적 형변환.
//Derived derivedTest = baseTest; //부모에게 자식은 안들어감. 그래서 오류 발생
baseTest = derivedClass as Base; //as문, derivedClass가 Base에게 상속을 받았는지 체크. 안받았으면 NULL;
- Base basetest = derivedClass; : Base를 사용하는 basetest 변수를 선언하는데 derived Class를 사용한다는 뜻
- 위는 (Base)derivedClass;와 같은 뜻입니다. 묵시적과 명시적의 차이입니다.
- baseTest = derivedClass as Base; : as문으로 derivedClass가 Base에게 상속받았는지 체크하는 코드입니다.
- abstract(추상) && Interface(약속)
//Base.cs
abstract class Base
{
//순수 가상 함수
//public virtual void Foo();
public abstract void Foo(); //이 문법 쓰려면 class 자체에 abstract를 붙여야함. 추상함수
//Overloading, Overload
//메소드 명이 같다.
//매개변수의 타입이 다르다.
//매개변수의 갯수가 다르다.
//반환형은 영향을 미치지 않음.
public void Foo(int _val)
{
Console.WriteLine("Base Foo Call: {0}", _val);
}
}
//////////////////////////////////////////////////////////////
//IInterface.cs
interface IInterface
{
//private면 함수 또는 변수가 오류
//상속을 다루는 virtual과 함께 재정의(override)를 위한 기능들이기 때문에
//private은 다룰 수 없어 오류가 발생한다.
//public int val; //너무 필드가 커서 오류 발생
public void Foo();
}
- abstract: 추상이라는 뜻으로 기능이 정해져있지 않은 함수, 메서드를 우선 선언만 해놓을 때 사용합니다. 게임으로 예시를 들자면, 기획 단계에서 Foo()라는 함수명을 선언했지만, 어떤 기능을 정의할지 판단이 되지 않을 때, 우선 선언만 해놓고 자식 class에서 상속받을 때 사용합니다.
- Interface: interface는 일종의 약속으로 자식 class는 부모 class를 하나 밖에 상속받지 못하는데 Interface는 자식 class가 복수 상속이 가능합니다.
class Weapon : Base, Derived //C#은 여러 부모를 상속할 수 없음.
class Weapon : IInterface, IWeapon //interface는 복수 상속이 가능.
class Weapon에서 Base, Derived 두 부모를 상속받을 수 없지만 IInterface, IWeapon 두 Interface는 상속받을 수 있습니다.
- Virtual, OverLoad, Override
- Virtual: 부모 클래스의 메서드에서 사용되어 자식 클래스에서 해당 메서드를 재정의할 수 있다는 뜻에 사용합니다.
- Override: 자식 클래서에서 사용되며 부모 클래스의 virtual 메서드를 재정의할 수 있습니다. 덮어쓴다라고 생각하면 됩니다.
- OverLoad: 동일한 이름의 메서드를 여러 개 정의하되, 매개변수의 타입이나 개수를 다르게 하여 구분하는 것입니다.
//Base.cs
abstract class Base
{
//가상함수, 가상메소드
//Virtual Method Table
/*
public virtual void Foo() //Virtual 키워드 추가
{
Console.WriteLine("Base Foo Call");
}
*/
//순수 가상 함수
//public virtual void Foo();
public abstract void Foo(); //이 문법 쓰려면 class 자체에 abstract를 붙여야함. 추상함수
//Overloading, Overload
//메소드 명이 같다.
//매개변수의 타입이 다르다.
//매개변수의 갯수가 다르다.
//반환형은 영향을 미치지 않음.
public void Foo(int _val)
{
Console.WriteLine("Base Foo Call: {0}", _val);
}
}
//////////////////////////////////////////////////////////
//Derived.cs
class Derived : Base //상속받은 Base 내의 함수를 다루지 않으면 오류가 발생함.
{
//Overriding, Override
//부모가 가진 메소드와 형식이 같음.
public override void Foo() //부모의 Foo()값을 덮어쓰기할 것이기 때문에 override 키워드 붙이기
{
//부모 Foo가 호출.
//부모의 Foo를 재구성하고 싶으면 밑 코드는 필요없음.
//부모 base의 Foo함수가 추상(abstrct) 함수이기 때문에 이 코드는 잘못됨.
//base의 Foo값을 가져오라는 것이기 때문에 안된다는 뜻임.
//base.Foo();
Console.WriteLine("Derived Foo Call");
}
}
Base.cs, Derived.cs 두 스크립트 파일에서 3가지를 모두 사용하고 있습니다.
- Base 스크립트에서는 virtual, overload, abstract를 다루고 있습니다.
- abstract class Base로 보아 Base class는 추상 클래스라는 것을 알 수 있습니다. (어떤 것을 다룰지 정하지 않았다는 뜻)
- public abstract void Foo(); 는 추상함수로 이 코드를 사용하기 위해선 class를 추상 class로 설정해야합니다. 위의 class Base를 추상 클래스로 만든 이유가 바로 이 코드 때문입니다.
- public void Foo(int _val) { ... }에서 Foo() 함수는 이미 동일한 함수명이 존재하여 오류가 발생해야 하지만 ( ) 소괄호 안에 매개 변수를 추가하여 Foo()를 overload 한 것입니다. 주석으로 추가로 관련된 설명은 표시해 뒀으니 확인해 보시는 걸 추천드립니다.
- public override void Foo() { ... }는 자식 class인 Derived.cs에서 선언한 것으로 Base 클래스에서 선언한 Foo( ) 추상 함수를 상속받아 사용하는 코드입니다.
상속은 여러 스크립트 파일에서 다뤄야할 동일한 특정 동작을 부모로, 그것을 사용할 자식 클래스로 나눠 같은 코드를 사용할 불편함과 유지 보수에 좋은 코딩 방법입니다.
끝
'프로그래밍 C#언어' 카테고리의 다른 글
템플릿(Template) (1) | 2024.09.09 |
---|---|
상속3 (0) | 2024.09.09 |
상속 (Inheritance) (0) | 2024.08.30 |
String (문자열) (0) | 2024.08.30 |
구조체 (Structure) (1) | 2024.08.29 |