Information Security Study
변수, 클래스 본문
C# 변수
변수
- 데이터 (숫자, 문자 등)를 저장하고 사용하기 위해 배정되는 공간을 지칭하는 이름
변수의 쓰임
- 게임 내부에서 데이터를 저장 / 사용하는 공간에 사용
- 화면에 보여지는 플레이어 이미지, 사운드 등 게임에 필요한 모든 정보가 저장됨
변수 선언
- 어떤 데이터를 저장 및 사용하기 위해 필요한 데이터 공간을 확보 후 그 데이터를 활용하는 범위, 데이터 속성, 공감을 지칭하는 이름을 설정하는 것
변수 타입
- 정수형
- 실수형
- 문자열
- 논리형
- 사용자정의형
기본 데이터 형식
- 정수
- 실수
- 논리
- 문자열
- 오브젝트
복합 데이터 형식
- 배열
- 구조체
- 클래스
부호가 있는 정수
정해진 크기 -1 만큼의 비트를 수로 표현하는데 사용하고, 나머지 1은 부호를 표현하는데 사용
- sbyte
- short
- int
- long
부호가 없는 정수
정해진 크기 만큼의 비트를 모두 수로 표현하는데 사용
- byte
- ushort
- uint
- ulong
문자 형식
- 정수 형식이지만 수가 아닌 한글자 문자 데이터를 다룬다
- 작은 따옴표로 문자를 감싼다
문자열 형식
- 여러개의 문자를 하나로 묶어 표현한다
- 문자열의 크기는 텍스트의 양에 따라 달라진다
- 큰 따옴표로 문자열을 감싼다
오브젝트 형식
- 어떤 데이터든 다룰 수 있는 형식이다
언박싱
- 힙에 있는 값 형식 데이터를 값 형식 변수에 할당하는 기능
- 오브젝트 형식의 데이터를 값 형식의 객체에 할당하면 오브젝트 형식은 언박싱을 시도해서 힙에 참조하고 있는 데이터를 복사하여 값 형식 객체에 저장
작은 정수 형식의 변수에 있는 데이터를 큰 정수 형식의 변수로 옮길 때
- 큰 정수 형식의 허용 범위가 더 크기 때문에 문제 없이 형식 변환이 가능하다
큰 정수 형식의 변수에 있는 데이터를 작은 정수 형식의 변수로 옮길 때
- 큰 정수 형식의 데이터 값이 작은 정수 형식의 최대 범위 안이면 가능하다
- 작은 정수 형식보다 큰 데이터를 넣을 경우 오버플로우가 발생한다
- 데이터의 원본이 훼손되어 다른 데이터가 저장된다
float와 double 사이의 형 변환
- 부동 소수점 형식의 특성상 오버플로우가 존재하지 않는다
- 소수점의 정밀도에 손상을 입는다
- float와 double은 소수를 이진수로 메모리에 보관한다
- 이것을 다른 형식으로 변환할 땐 10진수로 복원한 후 다시 이진수로 변환해 기록한다
- 1/3의 경우 0.3333..의 무한 소수로 표현된다
문자열 데이터를 숫자 데이터로 변환할 때
- Parse() 메소드를 이용한 형 변환
- 정수 형식, 부동 소수점 형식을 문자열로 변경할 때 사용
- TryParse() 메소드를 이용한 더 안전한 형 변환
- 형 변환에 성공했는지 여부를 논리형으로 알려준다
- Parse() 메소드는 형 변환에 실패하면 콘솔에 에러를 출력한다
객체 지향 프로그래밍
: 객체를 기반으로 하는 프로그래밍 (OOP, Object Oriented Programming)
- 프로그램을 여러 개의 독립된 객체 단위로 분할해 각각의 메시지를 주고 받고 데이터를 처리할 수 있다
- 프로그램 개발을 유연하게 할 수 있다
- → 유지/보수가 많다, 대규모의 소프트웨어 개발에 많이 사용된다
객체
: 세상의 모든 것을 지칭할 수 있다 (사람, 자동차 등)
: 추상적인 개념이다 (객체의 특징만 뽑아서 사용한다 - 속성과 기능으로 구분한다)
자동차
- 속성: 바퀴(개수, 크기, 재질 등), 핸들(반지름, 색상 등), 기어, 브레이크, 가속 페달 등
- 기능: 전진, 후진, 방향전환, 감속 등
클래스
: 객체를 표현하는 속성(변수)과 기능(메소드)을 하나의 집함으로 묶는 단위
public class 클래스 이름
{
// 변수(데이터와 메소드)
}
EX) 타코야끼를 만들 때
- 타코야끼 틀 = 클래스
- 만들어진 타코야끼 = 객체
EX) 플레이어 캐릭터 클래스
속성 (변수, 데이터)
: 플레이어 아이디, 체력
기능 (메소드)
: 데미지를 입어 체력 감소
public class Player : MonoBehaviour
{
private string ID = "캐릭터";
private int currentHP = 1000;
public void TakeDamage(int damage)
{
if(currentHP > damage)
{
currentHP -= damage;
}
}
}
Player: 클래스 이름
MonoBehaviour: 부모 클래스
ID, currentHP: 멤버 변수(필드)
TakeDamage: 멤버 함수(메소드)
멤버 변수 (필드, Field)
: 클래스에 소속된 변수로 클래스의 속성을 저장, 사용하기 위한 용도이다
: 같은 클래스에 소속되어 있는 메소드는 이 변수를 조건 없이 사용 가능하다
멤버 변수 선언 위치
- 클래스 중괄호 내부
- 메소드 정의 외부
- 메소드 내부에 선언된 변수는 멤버 변수가 아닌 지역변수이다
- 메소드가 종료되는 “)” 또는 return을 만나면 삭제되는 변수이다
멤버 함수 (메소드, Method)
: 클래스에 소속된 메소드로 클래스의 기능을 정의하고, 사용하기 위한 용도이다
: 같은 클래스에 소속되어 있는 메소드끼리는 조건 없이 호출 가능하다
메소드 선언 위치
- 클래스 중괄호 내부
- 메소드 정의 외부
- 다른 메소드 정의 내부에 메소드를 정의하지 않도록 주의!
접근 지정자
: 해당 멤버의 접근성을 설정하는 키워드이다
: 멤버 변수, 멤버 함수의 앞에 작성한다 (지역 변수는 사용 불가능)
public
: 외부에서 클래스를 통해 접근할 수 있다
private
: 외부에서 접근할 수 없으며, 하위 클래스에서도 접근할 수 없다
protected
: 외부에서 접근할 수 없으며, 하위 클래스에서는 접근할 수 있다
private는 default 지정자
→ 접근 지정자를 표기하지 않으면 private로 자동 설정
- 멤버 변수의 경우 특별한 경우에만 public을 사용한다
- internal, protected internal, private protected와 같은 접근 지정자도 있다
접근 지정자의 사용 이유
- 객체 지향은 클래스에서 최소한의 기능을 외부로 노출한다 (클래스의 은닉성)
- 현재 클래스 내부에서만 사용하는 기능의 경우 외부로 노출할 필요가 없다
EX) TV 사용 시
- 리모컨을 조작하는 것이 사용자의 일
- 실제로 화면에 색이 어떻게 표현되고, 소리가 어떤 원리로 나는지 몰라도 된다
따라서 클래스 내에 있는 각 멤버(변수, 메소드)를 필요에 따라 외부에서
사용 가능하도록 하거나 사용할 수 없도록 설정하는 것이 접근지정자!
클래스의 이용
- 클래스도 변수 데이터로 활용 가능하다(int, float 등과 동일)
- 멤버 변수, 지역 변수, 매개 변수, 반환 값 등에 모두 사용 가능하다
public class Enemy
{
private Player player;
public void AttackToTarget(Player target)
{
target.TakeDamage(100);
}
}
- Enemy 클래스에서 Player 타입의 멤버 변수 player를 선언
- AttackToTarget의 매개변수로 Player 타입의 target을 선언
클래스 객체 생성
- 클래스는 변수와 다르게 선언만으로는 사용할 수 없다
- new 키워드를 사용해 생성해야 사용 가능하다
- .을 사용해 해당 클래스의 멤버(변수, 메소드)에 접근 가능하다
생성자
: 객체가 생성될 때 자동으로 호출되는 메소드 (new로 메모리를 할당할 때)
: 생성자는 클래스 이름과 동일하게 정의한다
생성자 메소드 오버로딩
- 생성자는 필요에 따라 매개변수를 사용할 수 있다
- 메소드 오버로딩을 이용해 다양하게 정의해서 활용 가능하다
소멸자
: 객체가 소멸할 때 자동으로 호출되는 메소드 (가비지 컬렉터가 호출을 담당)
: 소멸자는 “~클래스 이름”과 같이 정의한다
- 소멸자의 한정자는 private
- 반환 형식과 매개변수를 가질 수 없다
- 메소드 오버로딩 사용이 불가능하다
얕은 복사
public class GameController : MonoBeheviour
{
private Player player01;
private Player player02;
private void Awake()
{
player01 = new Player("참가자", 1000);
player02 = player01;
player02.ID = "유니티";
Debug.Log($"ID : {player01.ID}");
Debug.Log($"ID : {player02.ID}");
}
}
출력 결과
ID : 유니티
ID : 유니티
클래스는 참조 형식이다
- 힙 영역에 객체를 할당한다
- 스택 영역에 있는 참조 변수가 힙 영역에 할당된 메모리의 주소를 가리킨다
깊은 복사
public class GameController : MonoBeheviour
{
private Player player01; // 스택 영역에 클래스 변수 생성
private Player player02;
private void Awake()
{
player01 = new Player("참가자", 1000); // 힙 영역에 메모리 할당
player02 = player01.DeepCopy();
player02.ID = "유니티";
Debug.Log($"ID : {player01.ID}");
Debug.Log($"ID : {player02.ID}");
}
}
public class Player
{
public string ID;
private int currentHP;
public Player DeepCopy()
{
Player clone = new Player();
clone.ID = ID;
clone.currentHP = currentHP;
return clone;
}
}
this 키워드
- 클래스의 변수나 메소드에 접근할 때는 대상이 필요하다
- 클래스 내부에서 자기 자신의 변수나 메소드에 접근할 때 this를 사용한다
- 변수 이름, 메소드 이름만 사용할 경우 default로 this가 자동 지정된다
public class Player
{
public string ID = "이름";
public SetID(string ID)
{
Debug.Log($"ID : {ID}");
Debug.Log($"ID : {this.ID}");
}
}
클래스 멤버 변수와 메소드 내부 지역 변수 이름이 같을 경우
- ID와 같이 이름만 사용하면 지역 변수를 지칭하게 된다
- this.ID와 같이 클래스 멤버 변수를 지칭하도록 사용한다
public class GameController
{
private void Awake()
{
player01.SetID("유니티");
}
}
this() 생성자
- this를 이용해 생성자를 호출할 수 있다
- 이미 정의된 생성자를 this()와 같이 호출해서 사용한다
정보 은닉
: 클래스 외부에서 클래스의 멤버 변수에 직접 접근하지 못하도록 멤버 변수를 private으로 선언하는 것
- 변수는 데이터를 저장 및 사용하기 때문에 직접 접근할 수 있도록 할 경우 들어가면 안 되는 값을 넣어 오류가 발생할 수 있다
캡슐화
: 정보 은닉으로 인해 클래스 외부에서 접근 불가능한 멤버 변수의 값을 조작할 수 있도록 생성하는 멤버 함수
- 일반적으로 변수명 앞에 Set, Get을 붙여 메소드 명으로 사용한다
상속 (Inheritance)
: 부모(기반) 클래스가 한정자로 정의된 변수와 메소드를 자식(파생) 클래스에게 제공하는 것을 뜻한다
상속을 하는 이유
- 여러 클래스에 동일하게 작성되는 내용은 부모 클래스로 작성한 후 자식 클래스가 상속 받아 사용하면 코드 간결화에 도움이 된다
- 형식을 통일해 하나의 그룹(배열, 리스트)으로 관리할 수 있도록 한다(업 캐스팅, 다형성 등의 추가적인 기법 필요)
- Player 클래스에는 ID, currentHP 멤버 변수에 대한 선언과 RecoveryHP(int) 메소드에 대한 정의가 없지만 부모 클래스인 Entity 클래스에 public, protected로 정의되어 있기 때문에 자식 클래스인 Player에서 자신이 정의한 것처럼 사용이 가능하다
base 키워드
: 부모(기반) 클래스의 변수나 메소드에 접근할 때 사용하는 키워드
this 키워드는 자기 클래스 내부의 변수, 메소드에 접근할 때 사용하는 키워드다
상속 관계에서 생성자와 소멸자 호출 순서
Entity의 생성자 → Player의 생성자 → Player의 소멸자 → Entity의 소멸자
다형성
: 객체가 여러가지 다양한 형태를 가지는 것을 뜻한다
: 상속을 받는 자식 클래스가 다양한 형태를 가지게 된다
다형성의 첫 번째 과정 [업 캐스팅 (Up-Casting)]
- 부모 클래스의 참조 변수에 자식 클래스의 객체를 참조하는 것이 가능하다 (부모 클래스의 객체 변수에 자식 클래스 메모리 할당이 가능하다)
- 부모 클래스와 자식 클래스 사이에 형 변환이 가능하다
is와 as 연산자
: 프로그램 실행 단계에서 형 변환이 가능한지, 형 변환에 성공했는지 확인한다
is 연산자
- 객체가 해당 형식에 해당하는지 검사한 후 그 결과를 bool 값으로 반환한다 (값, 참조 형식 모두 사용 가능)
as 연산자
- 형식 변환 연산자와 같은 역할로 형 변환이 가능하면 형 변환을 해서 인스턴스를 반환하고, 형 변환에 실패하면 null을 반환한다 (참조 형식에만 사용 가능)
'밀집 사고 예측 시뮬레이션 프로젝트 > C# Study' 카테고리의 다른 글
프로퍼티, 컬렉션, 일반화 프로그래밍 (0) | 2024.03.14 |
---|