unity 기본12 - scope, 캡슐화, getter, setter, public, private, protected

1. for문

 

for문을 만들고, for문 내부에 x = 2;를 선언

 

for문 밖에서 x를 출력해본다면?

 

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

public class HelloWorld : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        for (int i = 0; i < 10; i++)
        {
            int x = 2;
            Debug.Log(i);
        }

        Debug.Log(x);
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

 

 

for문 밖의 x에 빨간줄이 그어지는데

 

for문 내에서 만든 변수는 밖에서 쓸 수 없다

 

바깥에서 내부 스코프에 있는 변수는 접근할 수 없다

 

 

etc-image-0

 

 

 

마찬가지로 for문 initializer에서 만든 i도 밖에서 쓸 수 없다

 

etc-image-1

 

 

 

---------------------------------------------------------------------------------------------------------------------------------------------------

 

for문보다 먼저 int x = 4;를 선언하고 for문 내에서 int x = 2;를 선언하면?

 

에러가 난다

 

Start()함수 내에, for문보다 상위 스코프에서 선언된 int x = 4;를

 

하위 스코프 for문 내부에서 동일한 이름으로 int x = 2;로 재선언 하는 것을 허용하지 않는다

 

 

etc-image-2

 

 

 

이미 x = 4;가 있으니까 에러나는건가? 그렇게 생각해서 for문 뒤에 int x = 4;를 한다면?

 

그래도 에러가 난다

 

이건 좀 신기한데

 

etc-image-3

 

 

 

c#은 동일한 스코프 내에서 동일한 이름의 변수를 다시 선언할 수 없다

 

etc-image-4

 

 

 

 

 

2. 사용자 정의 함수

 

어떤 함수 내에서 만든 int x = 2;와 Start() 함수 내에서 만든 int x = 4;는 다른거라 에러가 나지 않는다

 

Hamsu() 내의 int x = 2;를 아무리 바꿔도, Start() 내의 int x = 4;에는 영향을 미치지 않는다

 

Hamsu()랑 Start()는 전혀 다른 스코프라 서로 영향을 미치지 않는다

 

etc-image-5

 

 

 

 

3. class의 멤버변수

 

HelloWorld class의 멤버변수로 int x;를 만들더라도, 내부 method내에 int x를 선언해도 에러나지 않는다

 

내부 method에서 만든 x와 멤버변수 x는 서로 다르다

 

etc-image-6

 

 

 

method내에서 멤버변수 x에 접근하고 싶으면 this.x로 접근

 

etc-image-7

 

 

 

 

4. 캡슐화

 

객체를 통해 프로그램 내에서 구현했을 때 밖에서 보여야 하는 것은 보이는 게 좋고 보일 필요가 없는 것은 안보이는 것이 좋다

 

객체: 인간

 

method: 먹는다

 

먹는다라는 기능을 구현하고자 할 때, 입에 넣는다 > 씹는다 > 삼킨다 > 식도를 지나친다 > 위장 > 소장 > 대장 > ...

 

이러한 과정을 밖에서 일일이 알 필요는 없다

 

쓸데없는 것이 많이 보이면 혼란스러울 뿐

 

객체가 캡슐이 되어 내부에 뭐가 들어있는지 신경쓰지 않아도, 내부의 내용을 다 가져다 쓸 수 있는 것

 

먹는다라는 결과만 보이면 된다

 

public : 누구나 다 볼 수 있는 내용, 외부에서 해당 멤버변수에 접근 가능

 

protected : public과 private의 중간쯤... 외부에서는 모르지만 자식 클래스는 아는 내용

 

private: 밖에서 볼 수 없는 것(자식 클래스도 모름), 외부에서 해당 멤버변수에 접근할 수 없음

 

아무것도 설정하지 않으면, C#은 기본적으로 private으로 설정함

 

etc-image-8

 

 

5. 캡슐화 예시

 

설정하지 않은 멤버변수 name, hp는 기본값 private

 

method들이나 class 앞에 public으로 설정

 

public이기 때문에 class 밖에서 method들을 호출할 수 있음

 

만약 method앞에 private으로 설정하면 밖에서 method를 호출할 수 없음

 

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

public class Character
{
    string names;
    int hp;

    public Character()
    {

    }

    public Character(string characterName, int initialHP)
    {
        names = characterName;
        hp = initialHP;

    }

    public void Hit(int damage)
    {
        hp -= damage;
    }

    public void Heal(int heal)
    {
        hp += heal;
    }

    public bool isAlive()
    {
        return hp > 0;
    }

    public void Eat(Food food)
    {
        if (isAlive())
        {
            hp += food.hp;
        }
    }
}

 

 

 

private은 자식 클래스도 호출불가능함

 

etc-image-9

 

 

 

만약 멤버변수를 public int hp;로 설정하면?

 

etc-image-10

 

 

 

자식 클래스에서 에러나지 않는다

 

 

etc-image-11

 

 

 

HellowWorld에서 Character instance를 만들고, hp에 접근하면 접근이 가능하고 값을 집어 넣을 수도 있지만

 

private인 names에는 접근 불가

 

etc-image-12

 

 

 

멤버변수 hp를 protected로 바꾼다면?

 

etc-image-13

 

 

 

HelloWorld인 완전 외부에서는 hp에 접근 불가

 

etc-image-14

 

 

 

하지만 private와는 다르게 자식 클래스 Wizard에서는 hp에 접근할 수 있다

 

etc-image-15

 

 

 

이런 보호수준을 지정하는 이유는 마음대로 누군가가 바꾸는 것을 방지하기 위함

 

무작정 public으로 해버리면 코드가 복잡해질 수록 꼬여서 고치기 힘들어질 수 있다

 

 

6. getter & setter

 

getter은 값을 get하는 곳이고 setter은 값을 set하는 곳

 

외부에서 보호중인 멤버변수에 접근하고자 할 때, 한 곳에서만 접근할 수 있게 만들어 준다

 

Character class의 hp를 private으로 바꾸고

 

etc-image-16

 

 

 

 

외부에서 hp에 값을 넣고 싶다면?

 

단순히 접근하면 불가능함

 

etc-image-17

 

 

 

다음과 같이 GetHp()와 SetHP(hp)를 정의

 

GetHP()는 현재 멤버변수 hp를 return

 

SetHP(hp)는 hp를 받아 멤버변수 hp를 parameter로 받은 hp로 설정

 

etc-image-18

 

 

 

이 method들은 public이라 외부에서 접근 가능한데, 

 

이제 이 method들을 통해서 Character의 멤버변수를 바꿀 수 있다

 

etc-image-19

 

 

 

그냥 멤버변수를 public으로 설정하고 raiden.hp = 10;으로 바꾸는게 편하지 않나?

 

하지만 이렇게 setter, getter를 설정하면...

 

1) 예를 들어 hp를 설정할 때 어떤 처리 (mp도 초기화된다든지)해야한다면 setter안에 그러한 처리도 설정해줘서

 

코드 관리가 편하다

 

그리고 2) 값을 접근할 수는 있지만 변경할 수는 없게 하고 싶다면 getter만 남기고, setter은 지우면 된다

 

----------------------------------------------------------------------------------------------------------------------------------------------------

 

 

7. get & set

 

이런 getter와 setter은 많이 쓰이다 보니.. 편하게 만드는 방법이 있다

 

public int hp

{

get; set;

}

 

etc-image-20

 

 

 

얘를 사용하는 방법? raiden.hp = 10;으로 setter를 사용할 수 있는데...

 

etc-image-21

 

 

 

이러면 public이랑 똑같은거 아닌가?

 

하지만 set;을 지운다면?

 

etc-image-22

 

 

 

setting이 불가능해진다

 

etc-image-23

 

 

 

하지만 raiden.hp에 접근은 가능함

 

etc-image-24

 

 

 

이렇게 만들때도, 다음과 같이 get, set 내부에 원하는 기능을 추가할 수 있긴 있다

 

public int hp;

{

get

{

return hp;

}

}

 

etc-image-25

 

 

 

set의 매개변수는 value로 고정되어있는듯? 다른거 쓰면 에러남

 

-------------------------------------------------------------------------------------------------------------------------------------------

 

다른 방법으로는 다음과 같이 private int hp; public int HP; 2가지 변수를 설정하고

 

HP 내부에 hp와 관련된 get, set을 설정

 

etc-image-26

 

 

 

이렇게 하면 실제 hp 변수는 hp지만, 외부에서 hp에 접근하고 싶으면 HP를 이용해서 접근해야한다

 

 

etc-image-27

 

 

728x90