상속 3번째 글입니다. 상속을 많이 다루는 이유는 한 프로젝트에 여러 스크립트를 다뤄야하는데, 그 과정에서 생기는 불상사를 방지하기 위해서입니다. 새로운 개념들을 다뤄보겠습니다.
//Program.cs
class Program
{
static void Main()
{
Magician magician = new Magician();
magician.Use();
}
}
////////////////////////////////////////////////////
//IElement
interface IElement
{
void Use();
}
/////////////////////////////////////////////////////////////////
//ElementFire.cs
class ElementFire : IElement
{
public void Use()
{
Console.WriteLine("Fire Ball");
}
}
////////////////////////////////////////////////////
//Magician.cs
class Magician
{
//상속: IS-A
//소유: HAS-A
//Coupling (결합도, 응집도) 밑은 종류.
//Tight Coupling (끈끈한 커플링)
//Loose Coupling (느슨한 커플링)
private MagicWand magicWand = null;
public Magician() //시작하자마자 동적할당을 <내부>에서 바로 만들어진 형태, 그래서 타이트 커플링
{
magicWand = new MagicWand(new ElementFire()); //매직완드에 불 속성 추가
}
public void Use()
{
if (magicWand != null)
{
magicWand.Use();
}
}
}
//////////////////////////////////////////////////////////////////
//MagicWand.cs
class MagicWand
{
private IElement element = null; //Loose Coupling(느슨한 커플링 중)
//의존성 주입(Dependency Injection): 커플링 과정 중 느슨한 커플링에 필요함
public MagicWand(IElement _element)
{
element = _element;
}
//Initialization (초기화 함수)
//게이름 초기화(Lazy Initalizaion)
public void Init(IElement _element)
{
element = _element;
}
public void Use()
{
//if (element != null) return;
element?.Use(); //이 코드의 기능이 위와 같음.
}
}
상속에는 IS-A(상속)와 HAS-A(소유)라는 개념과 Coupling이라는 개념이 존재합니다.
<IS-A관계 특징>
- 상속 표현: 상속을 통해 표현하며 특정 클래스가 다른 클래스의 특성을 상속받습니다.
- 다형성: 상위 클래스의 인스턴스를 하위 클래스의 인스턴스로 대체 가능합니다.
- 상, 하위 클래스의 관계: 상위 클래서가 더 일반적인 개념을 나타내며, 하위 클래스가 그 상위 클래스의 특수화된 형태를 나타냅니다.
- 코드 재사용: 상위 클래스에서 정의된 메서드와 속성을 하위 클래스가 상속받아 사용할 수 있으므로 코드 재사용이 용이합니다.
<HAS-A관계 특징>
- 객체 포함을 통한 표현: 객체를 포함하거나 참조함으로써 표현됩니다. 한 클래스가 다른 클래스의 인스턴스를 멤버 변수로 갖습니다.
- 구성 또는 집합: 구성은 클래스가 다른 클래스의 인스턴스를 강하게 소유하는 관계를 의미하며, 집합은 덜 강한 관계를 나타냅니다.
- 유연성: 더 유연한 설계가 가능한데, 여러 객체 간의 관계를 명확히 정의할 수 있습니다.
<Coupling 특징>
- Tight Coupling(끈끈한 커플링): 클래스가 직접 다른 클래스의 구현에 의존하는 것을 의미합니다.
- Loose Coupling(느슨한 커플링): 클래스 간 의존성이 적고 유연한 관계를 의미합니다.
위의 4가지 개념을 이해하고 코드에서 어떻게 다뤘는지 찾아보겠습니다.
<IS-A>(상속)
// IElement.cs
interface IElement
{
void Use();
}
// ElementFire.cs
class ElementFire : IElement
{
public void Use()
{
Console.WriteLine("Fire Ball");
}
}
위의 코드는 IS-A 상속 관계를 가지고 있습니다. class ElementFire : IElement 문을 통해 상속관계를 명확하게 표시하였고, Use() 함수의 기능을 추가하였습니다.
- Use() 함수에 추가된 기능: 함수 사용 시 Fire Ball을 출력
<HAS-A>(소유)
// MagicWand.cs
class MagicWand
{
private IElement element = null;
public MagicWand(IElement _element)
{
element = _element;
}
public void Use()
{
element?.Use();
}
}
// Magician.cs
class Magician
{
private MagicWand magicWand;
public Magician()
{
magicWand = new MagicWand(new ElementFire());
}
public void Use()
{
magicWand.Use();
}
}
위의 코드는 Magician class가 MagicWand를 소유하고 있는 HAS-A 관계입니다. : 를 통해 직접적으로 상속하지는 않았지만 MagicWand를 사용하는 magicWand 변수를 만들어 다루고 있습니다.
<Tight Coupling>(타이트 커플링)
// Magician.cs
class Magician
{
private MagicWand magicWand;
public Magician()
{
magicWand = new MagicWand(new ElementFire()); // 타이트 커플링: Magician은 MagicWand와 ElementFire에 직접 의존
}
public void Use()
{
magicWand.Use();
}
}
위의 코드에서 Magician이 MagicWand, ElementFire의 인스턴스를 직접 생성하고 있으므로 Magician과 MagicWand 사이의 의존성이 강하게 설정되어 있습니다.
- public Magician() { magicWand = new MagicWand(new ElementFire()); } 에서 직접적으로 인스턴스 생성 중
<Loose Coupling>(느슨한 커플링)
// MagicWand.cs
class MagicWand
{
private IElement element;
public MagicWand(IElement _element)
{
element = _element;
}
public void Init(IElement _element)
{
element = _element;
}
public void Use()
{
element?.Use();
}
}
위의 코드에서 MagicWand 클래스는 추상화된 IElement 인터페이스를 통해 ElementFire과 느슨하게 연결되어있습니다.
위의 코드에서 새로운 연산자가 등장했습니다.
- element?.Use(); : element가 null이 아닌 경우에만 Use() 메서드를 호출하도록 하는 구문입니다. '.?' 이것을 null 조건부 연산자(null conditional operator)라고 부릅니다. 위의 element에는 종합적으로 Fire Ball이 들어가 있기 때문에 Program class에서 Use() 메서드가 호출되고 Fire Ball이 출력됩니다.
끝
'프로그래밍 C#언어' 카테고리의 다른 글
컬렉션(Collections) (0) | 2024.09.09 |
---|---|
템플릿(Template) (1) | 2024.09.09 |
상속2 (5) | 2024.09.05 |
상속 (Inheritance) (0) | 2024.08.30 |
String (문자열) (0) | 2024.08.30 |