보통 변수를 만들고 나서 Set, Get 함수를  구현하여 변수를 읽고 쓰고 합니다. 변수를 추가할 때 마다 매번 생성해야하는 불편함이 있었는데요. C#에서는 이를 단순화하는 프로퍼티라는 변수를 제공합니다. 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Person
{
    // 기본 프로퍼티 사용법
    private int age;
    public int Age { get { return age; } set { age = value; } }

    // 프로퍼티도 데이터 은닉화를 할 수 있다.
    private string name;
    public string Name { get { return name; } private set { name = value; } }

    // 심플 프로퍼티 사용법
    public int weight { get; set; }
}

public class Test : MonoBehaviour
{
    void Start()
    {
        Person p1 = new Person();
        p1.Age = 10;
        print(p1.Age);

        // Name의 set 프로퍼티 앞에 private 키워드를 넣었기 때문에 아래 코드는 컴파일 되지 않는다.
        //p1.Name = "가나다";

        p1.weight = 70;
        print(p1.weight);
    }
}

 

출력 결과: 

'프로그래밍 언어 > C#' 카테고리의 다른 글

C# 형식 매개변수 T  (0) 2019.12.05
C# 인덱서  (0) 2019.12.05
C# 상속  (0) 2019.12.05
C# 델리게이트와 이벤트  (0) 2019.12.05
C# 구조체와 클래스 차이점  (0) 2019.12.04
Posted by 소블리애
,

상속을 설명하기 전에 부모 클래스와 자식 클래스를 두개 만들어 줍니다. 

 

Human.cs (부모 클래스)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

// 추상 함수를 쓰면 반드시 클래스도 추상 클래스가 되어야 한다.
abstract public class Human : MonoBehaviour
{
    protected string humanName;
    protected int humanAge;

    // 자식 클래스에서 함수 재정의를 하려면 부모클래스를 virtual로 선언해야 한다.
    protected virtual void Info()
    {
        print("나는 인간입니다.");
    }

    abstract protected void Name();
}

 

Student.cs (자식 클래스) 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Student : Human
{
    string schoolName;

    void Start()
    {
        schoolName = "티스토리";
        humanName = "소블리애";
        humanAge = 20;

        print(schoolName);
        Info();
        Name();        
    }

    // 부모 클래스의 Info함수를 재정의 한다.
    protected override void Info()
    {
        base.Info();
        print("나는 학생입니다");
    }

    // 만약 Name 함수를 재정의를 안했다면 컴파일 에러가 발생하게 된다.
    // 추상 함수는 자식 클래스에서 반드시 재정의를 해줘야 한다.
    // 프로그래머의 코드 누락을 방지하기 위한 방법.
    protected override void Name()
    {
        print(humanName);
    }
}

 

결과 화면 

위에 코드를 보면 학생은 인간임으로 논리적으로 상속이 성립합니다. 부모 클래스로 부터 상속 받은 자식 클래스는 부모에서 생성된 멤버 변수를 기본적으로 갖게 됩니다. humanName과 humanAge가 그렇습니다. 또한 자식 클래스에서 함수를 재정의 하여 쓸 수도 있습니다. 이때 반드시 부모 클래스에 가상함수(virtual)라고 알려줘야 합니다. 자식 클래스는 함수 이름 앞에 재정의(override) 키워드를 넣어주면 됩니다.

 

또한 반드시 작성해야 하는 함수(추상함수)를 갖게 되는 경우 부모 클래스에서 abstract 키워드를 함수와 클래스 앞에 넣어 줍니다. 그리고 구현 부분은 상속받은 자식 클래스에서 구현합니다. abstract를 붙여주는 이유는 해당 함수 및 클래스가 미완성인 상태를 명시 하는 것이다. 자식 클래스에서 해당 함수를 완성해야만 한다. 만약에 자식 클래스에서 구현을 하지 않았다면 컴파일 에러가 발생하게 됩니다. 이는 프로그래머가 반드시 작성해야 하는 코드임을 알려줄 수 있습니다. 

 

추가로 클래스 멤버 또는 함수에는 접근 한정자가 붙습니다. 용도는 아래와 같습니다.

 

public - 타 클래스에서 모두 사용 가능

private - 클래스의 내부에서만 사용 가능

protected - 상속 받는 자식 클래스만 사용 가능 

'프로그래밍 언어 > C#' 카테고리의 다른 글

C# 인덱서  (0) 2019.12.05
C# 프로퍼티  (0) 2019.12.05
C# 델리게이트와 이벤트  (0) 2019.12.05
C# 구조체와 클래스 차이점  (0) 2019.12.04
C# 얕은 복사와 깊은 복사  (0) 2019.12.04
Posted by 소블리애
,

델리게이트 

여러 함수가 중복적으로 사용될 때 델리케이트를 이용하여 함수를 등록하면 손 쉽게 함수를 관리 할 수 있는 기능이다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Test : MonoBehaviour
{
    public delegate void DeleFunc(int value);
    DeleFunc deleFunc;

    int hp;
    int mp;

    public void setHp(int value)
    {
        hp += value;
    }

    public void setMp(int value)
    {
        mp += value;
    }

    void Start()
    {
        deleFunc += setHp;
        deleFunc += setMp;

        deleFunc(5);

        print(hp);
        print(mp);
    }
}

출력 결과

5

5

 

델리케이트에 함수를 등록할 때는 += 연산자를 이용한다. 반대로 뺄 때는 -= 연산자를 이용하면 된다.

 

이벤트

이벤트는 서로 다른 클래스에서 함수를 추가 시켜고 한번에 호출 할 수 있다. 이벤트를 테스트 하기 위해서 Test 코드를 약간 수정하고 Test2 코드를 새로 만들어서 테스트 하면 아래와 같다.

 

Test.cs 파일

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Test : MonoBehaviour
{
    public delegate void DeleFunc(int value);
    public static event DeleFunc OnStart;

    public int hp;
    public int mp;

    public void setHp(int value)
    {
        hp += value * 10;
        print("체력: " + hp);
    }

    public void setMp(int value)
    {
        mp += value * 2;
        print("마나: " + mp);
    }

    void Start()
    {
        OnStart += setHp;
        OnStart += setMp;

        OnStart(5);
    }
}

 

Test2.cs 파일

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Test2 : MonoBehaviour
{
    void Start()
    {
        Test.OnStart += LevelUp;
    }

    public void LevelUp(int value)
    {
        print(value + "레벨이 되었습니다.");
    }
}

 

출력 결과:

 

'프로그래밍 언어 > C#' 카테고리의 다른 글

C# 프로퍼티  (0) 2019.12.05
C# 상속  (0) 2019.12.05
C# 구조체와 클래스 차이점  (0) 2019.12.04
C# 얕은 복사와 깊은 복사  (0) 2019.12.04
C# Queue와 Stack 사용방법 및 차이점  (1) 2019.12.04
Posted by 소블리애
,
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public struct PersonStruct
{
    public int age;
}

public class PersonClass
{
    public int age;
}

public class Test : MonoBehaviour
{
    void Start()
    {
        // struct는 값 타입이기 때문에 내부적으로 new 연산자를 자동으로 호출한다. 
        PersonStruct personStruct1;
        personStruct1.age = 10;

        // new 연산자를 직접 써줘도 된다.
        PersonStruct personStruct2 = new PersonStruct();
        personStruct2.age = 20;

        // 클래스는 항상 new 연산자를 이용해 생성해야 한다.
        PersonClass personClass = new PersonClass();
        personClass.age = 30;
    }
}

 

C# 구조체와 클래스 차이점 

구조체는 값타입이라는것과 클래스는 참조 타입이라는 점에서 차이점이 있다. 구조체를 사용하는이유는 클래스 사용시에 참조로인한 시간적 비용적 낭비를 없애기 위해 사용한다. 구조체는 값 타입이기에 직접적으로 메모리에 접근하므로 낭비를 막을수 있다. C#에서는 크기가 작고 단순한 함수들을 포함하는 선, 컬러 들과 같은 그래픽요소등을 구조체로 정의해두었다. 또한 구조체와 클래스의 다른점은 구조체는 상속자체가 불가능하다.

Posted by 소블리애
,

객체를 복사할 때 참조만 살짝 복사하는 것을 얕은 복사(Shallow Copy)라고 하고 객체를 복사할 때 별도의 힙 공간에 객체를 보관 하는 것을 깊은 복사(Deep Copy)라고 합니다. 쉽게 말해 데이타를 복사 했을 때 원본의 내용까지 같이 바뀐다면 얕은 복사이고 원본의 내용은 유지하고 싶다면 깊은 복사 입니다.

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MyClass
{
    public int a;
    public int b;

    public MyClass DeepCopy()
    {
        MyClass newCopy = new MyClass();
        newCopy.a = this.a;
        newCopy.b = this.b;

        return newCopy;
    }
}

public class Test : MonoBehaviour
{
    void Start()
    {
        // 얕은 복사 (참조 형식)
        MyClass source1 = new MyClass();
        source1.a = 10;
        source1.b = 20;

        MyClass target1 = source1;
        target1.b = 30;

        print("얕은 복사");
        print(target1.a + " " + target1.b);
        print(target1.a + " " + target1.b);
      
        // 깊은 복 (값 형식)
        MyClass source2 = new MyClass();
        source2.a = 10;
        source2.b = 20;

        MyClass target2 = source2.DeepCopy();
        target2.b = 30;

        print("깊은 복사");
        print(source2.a + " " + source2.b);
        print(target2.a + " " + target2.b);
    }
}

출력 결과:

 

얕은 복사

10 30

10 30

 

깊은 복사

10 20

10 30

Posted by 소블리애
,

Queue 사용방법

Queue<int> queue = new Queue<int>();

// 큐에 값을 넣는다.
queue.Enqueue(1);
queue.Enqueue(2);

if(queue.Count != 0)
{
    // 큐에서 값을 꺼낸다.
    queue.Dequeue();
}

// queue를 출력하면 2가 나온다.

 

Stack 사용방법

Stack<int> stack = new Stack<int>();

// 스택에 값을 넣는다.
stack.Push(1);
stack.Push(2);

// 스택에 값을 꺼낸다.
stack.Pop();

// stack를 출력하면 1이 나온다.

 

차이점

Queue는 선입선출(FIFO)로 가장 먼저 들어온 원소가 가장 먼저 나가는 구조이다. 스택은 후입선출(LIFO)로 가장 늦게 들어온 원소가 가장 먼저 나가는 구조이다.
Posted by 소블리애
,

Hashtable 사용방법

// HashTable은 map처럼 key, value가 존재한다.
Hashtable hashTable = new Hashtable();
hashTable.Add("가", 123);
hashTable.Add("나", 456);

// hashTable["가"] 값을 출력하면 123이 출력 될 것이다.

 

Dictionary 사용방법

Dictionary<string, int> dictionary = new Dictionary<string, int>();
dictionary.Add("가", 123);
dictionary.Add("나", 456);

 

차이점

HashTable는 특정 자료형 뿐만 아니라 여러 자료형을 담을 수 있다. 하지만 Dictionary는 선언한 자료형에 맞춰서 데이타를 삽입해야 한다. ArrayList가 쓰기 편할만큼 데이타를 가져오거나 넣을때 그만큼 느리다. 
Posted by 소블리애
,

ArrayList는 배열과 유사한 컬렉션입니다.

ArrayList arrayList = new ArrayList();
arrayList.Add(10);
arrayList.Add(20);
arrayList.Add(30);
arrayList.Add("hi");
// 출력결과: 10, 20, 30, hi

arrayList.Insert(1, 25);
// 출력결과: 10, 25, 20, 30, hi

arrayList.Remove("hi");
// 출력결과: 10, 25, 20, 30

arrayList.RemoveAt(0);
// 출력결과: 25, 20, 30

arrayList.Clear();
// 출력결과: 모든 원소가 지워지게 됩니다.

List 사용방법

List<int> list = new List<int>();
list.Add(1);

 

차이점

ArrayList는 특정 자료형 뿐만 아니라 여러 자료형을 담을 수 있다. 하지만 List는 선언한 자료형에 맞춰서 데이타를 삽입해야 한다. ArrayList가 쓰기 편할만큼 데이타를 가져오거나 넣을때 그만큼 느리다. 

Posted by 소블리애
,