클래스에서 상속은 기본 클래스의 멤버를 동작을 그대로 이어가고 확장하는 형태를 말한다.
그리고 기본 클래스를 지정하지 않은 한 모든 클래스는 object 에서 파생된다.
캐스팅
부모 클래스 Item 클래스가 있다. 여기에서 이를 상속받은 클래스 Contact란 클래스가 존재한다면 다음과 같이 구성할 수 있다.
Contact contact = new Contact();
Item item = contact;
.
.
.
contact = (Contact)item; // 부모 클래스는 명시적으로 자식클래스로 캐스팅돼야한다.
//
//
//
item = (Item)contact;
파생 클래스인 Contact는 Item이기 때문에 Item 클래스형 변수에 직접 할당할 수 있다. (2번째 라인)
이 경우에는 형 변환이 캐스트 연산자 없이 일어 났다고 하여 "암시적 (혹은 묵시적) 변환"이라고 한다.
이런 경우는 에러를 발생시키지 않지만 이 반대에 경우는 조금 다르다.
Item 클래스가 꼭 Contact 클래스가 아닐 수도 있기 때문에 부모 클래스에서 자식 클래스로 캐스팅시에는 반드시 어떤 형태로 캐스팅될 것인지 알려주는 "명시적 캐스팅"이 필요하다.
접근 한정자
- private - private 으로 선언된 멤버는 이를 상속한 자식 클래스나 다른 외부에선 private 멤버 변수나 함수에 접근할 수 없다. 즉 private 멤버는 해당 클래스에서만 접근할 수 있도록 해주는 한정자이다.
- protected - private과 비슷하지만 자식 클래스에서 이 한정자의 멤버에 접근할 수 있는 권한이 생긴다.
봉인 클래스 sealed
sealed 키워드가 붙은 클래스는 상속이 불가능하다.
virtual 한정자
vritual 한정자가 붙은 멤버는 재정의를 허용한다는 의미를 갖는다. 재정의는 자식 클래스에서 지정할 수 있으며, 해당 한정자가 붙은 멤버를 필요에 의해 재정의하여 자식클래스만의 기능으로 재정의할 수 있게한다. 더불어 재정의를 할 경우 override 키워드를 붙여 사용해야 한다.
new 한정자
재정의 메소드에서 override 키워들 사용하지 않고 사용할 경우 컴파일러는 경고를 내뱉는다. 같은 이름을 가지지만 부모 클래스의 내용이 아닌 자식클래스만의 내용으로만 지정해야할 경우에 사용한다. override와 유사하지만 new 한정자는 해당 멤버를 숨긴다.
base 멤버
클래스의 멤버를 재정의를 선택할 때, 부모 클래스의 멤버를 호출하고 싶을 때 base 키워드를 사용하여 부모 클래스의 해당 멤버에 접근할 수 있다. 아래 코드는 Bullet 클래스에서 Awake 함수를 상속받은 EnemyBullet 클래스에서 접근하고 있는 모습이다.
public class EnemyBullet : Bullet
{
protected override void Awake()
{
base.Awake();
Physics.IgnoreLayerCollision(LayerMask.NameToLayer("EnemyAttack"), LayerMask.NameToLayer("Enemy"));
}
}
추상 클래스 (abstract)
추상 클래스는 추상적 개념을 위해 사용된다. 여기서 말하는 추상적 개념이란 앞으로 상속 받을 자식 객체들의 입장에서 동일한 이름의 개념(함수)을 정의하는 것을 말한다.
추상 클래스를 사용하기 위해선 abstract 키워드를 class 키워드 앞에 붙여 사용한다. 그리고 앞으로 상속자에게 개념을 정의시킬 멤버에게도 붙이며 내용은 정의하지 않는다.
위와 같이 정의된 추상 클래스는 객체를 생성할 수 없다. 당연히 멤버 함수의 내용이 정의되지 않았기 때문에 해당 클래스를 상속 받은 객체를 통해서 추상화된 개념을 정의 해야한다.
다형성
추상 클래스처럼 같은 이름으로 다양한 기능을 구현화하는 성질이다.
is와 as 연산자
C#에선 다운 캐스팅을 허용하기 때문에 변환전에 기본 형식을 알아낼 필요가 있다. 이 때 사용할 수 있는 is 연산자를 통해서 기본 클래스가 어떤 것인지를 확인할 수 있게 한다.
as 연산자는 is 보다 한 개념을 더 나아가는 연산자인다. is는 단순히 해당 클래스로 변환이 가능한지에 대한 여부만을 반환한다. 반면에 as 연산자는 해당 형식으로 변환 후 그 형식으로 취급하여 사용할 수 있다. 만약 해당 형식이 될 수 없다면 null을 반환한다.
해당 코드에선 is 연산자로 ActiveSkill 클래스로 상속한 Skill 클래스인지를 체크 한 후, as 연산자로 ActiveSkill로 변환해서 해당 멤버에 접근하는 형태이다.
public string GetSkillDesc(Skill skill)
{
string result = "";
if(skill is ActiveSkill)
{
value = (skill as ActiveSkill).MyDamage;
}
// ....
return result;
}
'개발 > C#' 카테고리의 다른 글
Event와 Delegate의 차이 (0) | 2024.06.13 |
---|---|
[C#] 인터페이스(Interface) (0) | 2024.05.14 |
부분 클래스 (0) | 2024.05.08 |
확장 메소드 (0) | 2024.05.08 |
전처리기 (0) | 2024.05.08 |