모름

Generic (일반화)

제네릭은 데이터 타입을 일반화 하여 사용함을 의미함;

class MyClass<T> {
	T typeVal;
    void SetType(T typeVal){
    	this.typeVal = typeVal;
    }
}

이러한 형태로 사용되는데, 여기서 T는 타입변수라고 하며 임의의 참조형 타입임을 의미한다. 위의 예시에서는 클래스에서 일반화를 사용했는데. 함수에서도 똑같이 사용이 가능함.

public void SetType<T>(T setValue){

}

제네릭을 통해 같은 함수에 여러 데이터 타입을 일반화하여 적용 할 수 있어 많이 유용한 문법이다.

 

 

Interface (인터페이스)

추상클래스와 인터페이스가 있다. 추상클래스와 인터페이스는 둘 다 어떠한 객체의 추상을 표현한다는데 공통점이 있다. 하지만 구현상에 차이가 있고, 이를 통해 추상 클래스는 인터페이스에 비해 강한 제한을 주는 클래스라고 보면 되고, 인터페이스는 좀 더 느슨한 추상을 객체에게 제공한다.

abstract class Human{
	public abstract void Walk();
}

//Human 추상 클래스의 Walk를 Man 클래스에 강제
class Man : Human{
	public override void Walk(){
    
    }
}

추상클래스(abstract)는 위와 같이 구현이 되는데, Human 추상 클래스에서 걷기라는 함수를 자식 클래스에게 강제하게 되고, 이를 통해 자식은 모두 동일한 인터페이스를 가지게 된다.

 

단 abstract는 다중 상속을 제공하지 않는다. 반대로 interface 를 사용하면 다중 상속이 가능한 인터페이스를 제공 할 수 있다.

interface IThinkable{
	void Think();
}

class Man : Human, IThinkable{
    public override void Walk(){}    
    public void Think(){}
}

abstract나 interface나 구현 상의 차이는 있지만, 어떤 추상이냐에 따라 적절하게 잘 사용하는게 중요하다.

 

 

Property (프로퍼티)

프로퍼티는 객체지향의 은닉성을 생각해봐야한다. 은닉성은 다른 객체가 몰라도 되는 숨겨야 되는 데이터를 잘 은닉시키는 것을 의미하는 속성이다. 이를 구현하기 위해 Property 문법을 활용 할 수 있다.

 

예를 들어 어떤 변수를 public이 아닌 함수로만 접근하게 한다면 변수를 은닉시키는 것이 된다. 이렇게 되면 장점이 많은데, 변수를 수정하기 위한 함수 내에서 뭔가 조건을 거는 등의 처리 로직을 덧 붙일 수 있기 때문이다.

private int hp;
public int Hp{
    get { return hp; }
    set { hp = value; }
    // private set {hp = value;} 도 가능
}

프로퍼티는 위와 같이 구현이 된다.

 

public int Hp {get; set;}

c#에서는 자동완성 프로퍼티를 제공하는데, 위와 같이 사용만 해도 프로퍼티로 활용이 가능하다. 물론 내부적으로는 앞서 본 코드와 마찬가지로 get, set 함수가 구현되고 있을 것이다.

 

Delegate (대리자)

대리자를 현실에 빗대어 비교해보자면, 맛집을 찾아갔다고 치자. 하지만 줄이 길어서 직원에게 사람이 빠지면 연락을 달라고 말하며 예약을 했다. 그럼 사람이 빠졌을 때 직원은 우리에게 연락을 주는데. 여기서 직원은 '사람이 빠지는 것을 기다리고 연락을 주는 행위' 를 대리해서 해주고 있는 것이다. 만약 직원이 이 역할을 대리해주지 않으면 우리가 직접해야하는데, 그럼 우리는 기다리면서 커피를 마시거나 산책도 못하고 사람이 빠질때까지 기다려야만 하는 것이다. 이것은 언뜻 보기에도 비효율적이다. 이래서 대리자라는 문법이 있는 것이다.

 

 대리자는 Unity 에서 UI를 작업할 때 많이 사용된다. 사용자가 버튼을 누를 때까지 기다려야하는데 이걸 대리자가 기다리다가 버턴이 눌려졌을 때 프로그램에게 알려주는 식이다. 근데 여기서 중요한 점은 우리는 버튼을 눌러졌을 떄 무엇을 할지에 대해서도 대리자에게 미리 이야기를 해두어야 한다는 점이다.

 

나는 버튼을 눌렀을 때 팝업창을 띄울거야라는 행위를 대리자에게 맡겨둔다. 그리고 대리자가 버튼 눌렀음을 콜백하면서 맡아둔 팝업창을 띄우는 행위까지 바로 호출해주는 식이다.

delegate in OnClicked();

public void ButtonPressed(OnClicked clickFunc){
	clickFunc();
}

public int ClickedAction(){
	return 0;
}

public void Start(){
	ButtonPressed(ClickedAction);
}

이걸 코드로 구현하면 위와 같이 사용할 수 있다.

 

delegate in OnClicked();
OnClicked onClicked = new OnClicked();

public void Start(){
    onClicked += ClickedAction;
    onClicked += ClickedAction2;
}

대리자를 만약 생성해서 사용하면 여러 행위들을 체이닝 하여 대리자에게 예약시킬 수 있기도 하다.

 

Event(이벤트)

앞서 델리게이트를 변수로 생성했을 경우 이를 다른 클래스에서도 접근하여 호출할 수 있다는 단점이 있는데, event 수식어를 붙이면 선언된 내부 클래스에서만 호출이 되고 외부에서는 호출할 수 없게 됩니다.

public delegate in OnClicked();
public event OnClicked onClicked;

생긴것도 델리게이트랑 거의 비슷하고, 둘 다 콜백방식이라는 점에서 매우 유사하다. 하지만 앞서 말한 결정적인 차이점은 알아둬야한다.

 

*참고로 닷넷 system 클래스에는 미리 구현되어있는 대리자 Action, Func 가 있는데 자주 쓰이는 델리게이트이다.

 

Lamda(람다식)

람다는 일회용 함수를 사용하는 문법이다. 코딩하다 보면 계속해서 반복해서 사용할 함수가 아닌, 딱 이 때만 사용할 일회용 메서드가 필요할 때가 있는데 람다식을 통해 구현하면 좋다.

 

Replection(리플렉션)

객체의 여러 모든 정보를 살펴 볼 수 있음.