본문 바로가기
C#/C# 학습 (TIL)

C# 중급문법 DAY1 추상클래스/인터페이스/콜렉션/foreach/var/object

by jjiing 2022. 6. 15.

중급문법 학습에 들어가기 전 

중급문법을 배우는 이유는?

 

사용하지 않아도 구현은 할 수 있지만

구현이 아니라 설계 부문에서 좀 더 확장이 용이하고/ 모듈화를 시키고/ 클래스끼리의 의존도를 낮추기 위해 배우는 것이다.







 

 

 

 

태그가 아닌 스크립트로 접근하기

private void OnTriggerEnter(Collider other)
    {
        if(other.GetComponent<Monster>() !=null)
        {
            other.GetComponent<Monster>().Hit(atk);
        }
    }

 

if(other.tag==”Monster”) 로 비교하는 경우 태그가 구체화되어 바뀌거나 늘어날 때 문제 발생

그냥 몬스터 스크립트를 가지고 있는 경우가 더 적절

  • 몬스터가 각각 다른 스크립트를 가지고 있는 경우에는?.. ex) 해당 종류에 해당하는 자식 스크립트만 가지고 있는 경우 : 가상함수 처리 해주면 됨(virtual & override)

 

(참고) 상속을 해주려면 public이나 protected인 것들만 상속이 됨

start 도 public으로 하면 자식에서 실행됨.

 

 

if(other.GetComponent<Monster>() !=null)

        {

            other.GetComponent<Monster>().Hit(atk);

 

        }

= 아래와 같은 의미

other.GetComponent<Monster>()?.Hit(atk); //변수? 만약 변수가 null이 아니라면 처리할 것

 

 

 

추상클래스

이 경우 몬스터는 더 이상 객체를 찍어내는 클래스는 아님 > 추상 클래스로 만들어준다

public abstract class Monster: Monster

>>더 이상 객체 생성 불가

>>최소 하나의 순수 가상함수를 가져야한다

>>순수가상함수? 추상함수? 정의가 돼있지 않은 가상함수

 

//추상함수 : 추상함수가 미구현돼있기 때문에 추상클래스는 완전한 클래스가 아님

//따라서 자식에서 추상함수를 꼭 무조건 구현(재정의)해줘야한다.

 

<실습 내용 클래스다이어그램화>

 

 

 

 

인터페이스

 

 

인터페이스 : 이 기능을 구현해주겠다는 약속

인터페이스(public interface ISwimable)를 매번 새롭게 구현해주는 것 보다 인터페이스를 상속받는 스크립트 public class Swimable :ISwimable 를 만들어서

그 스크립트를 오브젝트에 넣어주면 해당 인터페이스의 기능을 다 가지고 있음

근데 인터페이스를 상속받을 때 기능에 조금씩 차이를 주고싶다면 인터페이스를 상속받은 스크립트(Swimable)를 상속받아 재정의 해주면 된다. (가상함수 처리 해야함)

 

 

 

 

 

콜렉션

void Start()
    {
        List<int> intList = new List<int>();
        //c#에서의 리스트는 c++에서의 벡터 개념(동적 배열?)
        intList.Add(20);
        intList.Add(10);
        intList.Add(30);
        //이건 형태를 정해주는 제네릭 형태의 리스트

        ArrayList arrayList = new ArrayList();
        arrayList.Add(20);
        arrayList.Add("strig");
        arrayList.Add(0.5f);
        //비제네릭 형태의 리스트

        for (int i = 0; i < arrayList.Count; i++)
            Debug.Log(intList[i]);

        for (int i = 0; i < arrayList.Count; i++)
            Debug.Log(arrayList[i]);


        Queue<int> queue = new Queue<int>(); // 제네릭
        Queue nongenericQueue = new Queue(); //논 제네릭
        queue.Enqueue(5);
        queue.Enqueue(6);
        queue.Enqueue(7);
        queue.Enqueue(8);

        for (int i = 0; i < queue.Count; i++)   //큐는 이렇게 하면 안됨 카운트가 하나씩 줄어서
            Debug.Log(queue.Dequeue());

        while (queue.Count > 0)
            Debug.Log(queue.Dequeue()); //큐는 이렇게 해야함


        Stack<int> stack = new Stack<int>();
        
        while (stack.Count > 0)
            Debug.Log(stack.Pop());

Dictionary<string, Color> colorDic = new Dictionary<string, Color>();

        colorDic.Add("white", new Color(255, 255, 255, 255));
        colorDic.Add("Black", new Color(0, 0, 0, 0));

        Color color;
        color = colorDic["Black"];
        color = Color.black;

        Hashtable hashtable = new Hashtable();  //dictionary의 논제네릭
        hashtable.Add(1, "12");
        hashtable.Add("t", "sd");
        }

 

 

foreach

        foreach (int temp in intList)

            Debug.Log(temp);

 

        foreach (int temp in stack)

            Debug.Log(temp);

 

        foreach (int temp in queue)

            Debug.Log(temp);



 

var / object

        Test test = new Test();

        test.testValue = 10;

         

        var tempVar = test; // var 데이터 타입을 자동으로 맞춰주는데 맞춰주는 타이밍이 돌리기 전 컴파일 시점

       //데이터 타입을 자동으로 맞춰주었기 때문에 test의 고유한 속성인 testvalue를 참조할 수 있음

        

        //object는 가장 최상위의 데이터타입으로 모든 데이터 데이터타입은 object로 형변환 가능

        //object로 형변환되면 가지고 있던 고유한 속성은 숨겨지며(박싱)

        object tempObject = test; //박싱,언박싱

        ((Test)tempObject).testValue = 10;

        //해당 타입으로 다시 캐스팅(언박싱)하여 사용해야한다.



    }

    public class Test

    {

        public int testValue;

    }



 

 

구조체는 깊은 복사 (값이 복사)

클래스 얕은 복사 (주소가 복사)

String 은 예외