C#-(2) 기본 개념
연산자
연산자 개요
- 변수 데이터를 연산해 다양한 결과를 얻기 위해 사용
- 결과 값을 대입하는 대입 연산자부터 사칙연산을 하는 산술 연산자 등 제공

대입(할당) 연산자
- 결과값을 댕비하는 연산자로 여러 연산을 축약한 대입 연산자도 제공

비교(관계) 연산자
- 양쪽의 값을 비교하여 결과를 참(true) 또는 거짓(false)으로 나타내는 연산자

비교(관계) 연산자
- 양쪽의 값을 비교하여 결과를 참(true) 또는 거짓(false)으로 나타내는 연산자

조건(삼항) 연산자
- 조건식을 사용해 조건식의 참, 거짓 여부에 따라 다른 결과 값 대입

비트 연산자
- 비트 단위의 데이터 연산에 사용
- 시프트 연산의 장점 : 연산 속도가 빠르다
- 시프트 연산의 단점 : 머리로 계산이 잘 안된다

비트 논리 연산자

연산자 우선순위
- 연산자마다 우선순위가 정해져 있다
- 우선순위가 같을 경우 왼쪽의 연산자를 먼저 계산한다
- 괄호 안에 있는 연산자가 우선 계산된다
- 우선순위가 헷갈리면 괄호로 구분하는게 최고다

조건문
조건문 개요
- 조건문은 설정한 조건이 참(true) 또는 거짓(false)일 때 코드를 실행하거나 실행하지 않고 넘어가서 프로그램의 흐름을 여러 갈래로 나누는 제어문이다.
- 조건문에는 if와 switch-case가 있으며, if의 경우 if, else if, else로 나눌 수 있다

if
- if의 조건이 참이면 if 조건식 뒤의 중괄호 내부를 실행하고,
거짓이면 실행하지 않고 넘어간다

SerializeField 어트리뷰트
- ex) [SerializeField]
- ex) private int x = 10;
- 클래스 멤버 변수를 선언할 때 변수 앞 또는 바로 윗줄에 작성하면 유니티 에디터 Inspector View에서 해당 클래스 멤버 변수 값을 설정할 수 있다.
if-else
- if의 조건이 참(true)이면 if 중괄호 내부를 실행하고, 거짓(false)이면 else 중괄호 내부를 실행한다.

if-else if - else
- if의 조건이 참(true)이면 if 내부를 실행하고, 거짓(false)이면 else if의 조건 2를 실행한다
- else if의 조건 2가 참(true)이면 else if 내부를 실행하고, 거짓이면(false)이면 else를 실행한다

switch - case
- switch에 조건을 검사할 변수를 설정한다
- 조건에 해당하는 것이 case 뒤에 있는 값이다
- 위의 조건을 모두 만족하지 않을 때 제일 아래에 작성된 default가 실행된다 (if 조건문의 else와 같은 역할을 수행)
- switch - case에서 break는 중단의 역할을 하기 때문에 break가 없다면 다른 case의 조건도 이어서 실행하게 된다

반복문
반복문 개요
- 반복문은 설정한 조건이 거짓이 될 때까지 코드 블록 내부를 반복해서 실행한다
- 반복문에는 for, while, do-while이 있다

for
- for 괄호 내부에 초기화, 조건, 증감 연산자와 같이 3개의 연산자를 작성하며, 초기화한 변수가 반복문 내부를 1회 실행할 때만다 증감 연산자에 의해 값이 바뀜
- 이 값이 조건을 만족하지 않을 때까지 반복해서 실행한다.

while
- for와 다르게 괄호 내부에 조건만 들어간다
- 조건을 만족하지 않을 때까지 반복 실행하는 것은 동일하다
- 조건에 사용되는 변수의 초기화와 증감 연산은 알아서 작성해야한다
- 보통 초기화는 while()문 위의 작성하며, 증감 연산은 while()문 내부의 가장 아래에 작성한다
- 실행 구조는 for문과 유사하다.

do-while
- for, while문은 조건을 먼저 검사하기 때문에 조건이 맞지 않으면 단 1번도 실행되지 않는다.
- 반면, do-while은 일단 한번은 조건 없이 실행하고, 그 후에 조건을 검사해 반복해서 실행한다.

무한 루프
- 반복문은 정해진 회수만큼 반복한 후 종료하지만, 이를 정해진 회수 없이 무한하게 실행하도록 할 수 있다
- 반복문 내부 또는 다른 곳에서 이 반복문을 종료시킬 수 있는 코드를 반드시 작성해야한다.

무한 루프 사용 방법
- for 반복문은 세미콜론 사이에 들어가는 문장을 작성하지 않으면 된다
- while, do-while은 조건에 true를 작성해 조건이 계속 참이 되도록 설정한다
점프문 break, continue
- 흐름을 끊고 프로그램의 실행 위치를 원하는 곳으로 이동시킨다
- break : 현재 실행중인 반복문이나 switch문의 실행을 중단할 때 사용한다
- continue : 반복문에서 현재 조건을 건너뛴다
배열
배열이란?
- 같은 형식의 데이터를 한 그룹으로 묶어서 사용하는 것
배열이 필요한 이유?
- 5마리의 적이 있다고 가정할 때, 5마리의 적의 체력을 담는 변수 선언

- 만약 이러한 적이 50마리라고 한다면? 50개의 변수 선언 ?
- 변수를 50개 선언해야할까?
배열의 선언

배열에 값 저장하기

배열의 장점
- 선언 뿐만 아니라 사용할 때도 개수만큼의 줄 수가 필요한 변수와 달리 배열은 반복문을 이용해 한번에 사용 가능

배열의 초기화
-
첫번째 방법은 배열의 원소 개수를 명시, 그 뒤에 중괄호 { 와 }로 둘러싸인 블록을 붙인 뒤, 블록 사이에 배열의 각 원소에 입력될 데이터 입력

-
두번째 방법은 첫번째 방법에서 배열의 용량을 생략

-
세번째 방법은 new 연산자, 형식과 괄호 ‘[’ ‘]’배열의 용량 모두 생략

System.Array
- .NET 프레임워크의 CTS(Common Type System)에서 제공하는 배열
- Array 클래스의 주요 메소드와 프로퍼티

2차원 배열의 선언
- (세로 +가로) 형태로 된 배열로 차원의 크기를 콤마(,)로 구분해서 입력

가변 배열(Jagged Array)
- Jagged의 뜻은 “들쭉날쭉한” 이라는 뜻
- 말 그대로 1차원의 크기를 들쭉날쭉 다르게 설정할 수 있다

메소드
메소드란?
- 객체 지향 프로그래밍 언어에서 사용하는 용어
- 유사한 용어 (사용하는 언어에 따라 다르게 부르기도 한다)
- 함수 (Function)
- 서브루틴 (SubRoutine)
- 프로시져 (Procedure)
- 서브 프로그램 (SubProgram)
메소드 정의
- “방법”이라는 뜻으로 객체의 일을 처리하는 방법을 정의
- 일련의 코드를 하나의 이름 아래 묶은 것
- 묶어 놓은 코드는 메소드의 이름을 불러 내부 코드들을 실행할 수 있다

메소드의 예

메소드의 장점
- 일련의 코드를 묶어두고, 이름을 불러 내부 코드를 실행하기 때문에 동일한 내용의 코드를 반복해서 작성하는 수고가 적어진다
Return 이란?
- return이 호출되면 메소드를 종료, 프로그램의 흐름을 호출자에게 돌려준다
- 메소드 내부에서 변환된 특정 데이터를 반환하는 용도로 사용
매개 변수를 사용하는 이유?
- 매개 변수가 없으면 단순히 같은 내용의 코드를 반복 재생하는 정도
- 매개 변수가 있으면 메소드 내부에서 연산되는 결과가 다양하게 변화
값에 의한 전달 (Call By Value)
- Awake() 메소드의 a,b 값을 Add() 메소드의 매개 변수로 넘긴다면
- 넘겨지는 매개 변수 a, b는 Add() 메소드 안으로 들어가는 것일까 ?

참조에 의한 전달 (Call By Reference)
- 값에 의한 전달처럼 매개 변수가 변수나 상수로부터 값을 복사하는 것이 아닌 원본 변수를 직접 참조하는 방식
- 원본 변수를 참조 중이기 때문에 매개 변수를 수정하면 원본이 수정된다
- 사용방법 : 메소드의 정의와 호출에서 매개 변수 앞에 ref 키워드 사용

출력 전용 매개 변수
- return은 하나의 결과만 반환하는 것이 가능하다
- 2개 이상의 결과를 반환할 때는 ?
-
변경된 값이 유지되니까 ref 키워드를 사용할까?

- 출력 전용 매개 변수인 out 키워드 사용
- ref 매개 변수는 메소드 내부에서 결과를 저장하지 않아도 컴파일러가 아무런 경고도 하지 않는 반면,
- out 매개 변수는 메소드 내부에서 결과를 저장하지 않으면 컴파일 에러가 발생 (개발자의 실수를 줄여준다)

메소드 오버로딩
- 두 수를 더하는 Add() 메소드를 구현하는 경우
- 더하는 데이터 타입이 정수일 수도 있고, 실수일 수도 있다

- 동일한 메소드 이름으로 여러 종류의 메소드를 구현하는 것
- 매개 변수의 개수와 형식을 분석하여 메소드를 선택
- 반환 형식은 고려하지 않기 때문에 반환 형식만 다를 경우는 구분하지 못한다
가변 길이 매개 변수
- 개수가 유연하게 변할 수 있는 매개 변수
- 변수의 길이가 다른 메소드가 아주 많이 필요한 경우 사용

명명된 매개 변수
- 일반적으로 매개 변수에 데이터를 할당할 때 순서에 의거하여 할당하는 반면
- 순서에 상관 없이 매개 변수의 이름에 근거하여 데이터를 할당하는 방법
- 코드의 길이는 길어지지만 코드의 가독성이 높아진다

선택적 매개 변수
- 매개 변수를 특정 값으로 초기화 하지 않았을 때 기본 값을 할당하는 것
- 필요에 따라 매개 변수에 데이터를 할당하거나 할당하지 않을 때 사용
- 선택적 매개 변수는 항상 필수 매개 변수 뒤에 와야 한다

선택적 매개 변수의 예

- 주의! 메소드 오버로딩과 선택적 매개 변수를 아래와 같이 섞어쓰지 않도록 한다

객체 지향 프로그래밍
- 객체를 기반으로 하는 프로그래밍(OOP, Object Oriented Programming)
- 프로그램을 여러 개의 독립된 객체 단위로 분할해 각각의 객체들이 메시지를 주고 받고, 데이터를 처리할 수 있다
- 프로그램 개발을 유연하게 할 수 있어 게임과 같이 유지/보수가 많고, 대규모의 소프트웨어 개발에 많이 사용된다.
객체란?
- 세상의 모든 것을 지칭 (사람, 자동차 등)
- 추상적인 개념 (객체의 특징만 뽑아서 사용 - 속성과 기능으로 구분)
- 자동차 속성 : 바퀴(개수, 크기, 재질 등), 핸들(반지름, 색상), 기어, 브레이크, 가속페달 등
- 자동차 기능 : 전진, 후진, 방향 전환, 감속 등
클래스(Class)
- 객체를 표현하는 속성(변수)과 기능(메서드)을 하나의 집합으로 묶는 단위
- 타코야끼를 만들 때, 타코야끼 틀에 반죽 물과 문어를 넣고 타지 않게 돌리며 굽는다.
- 타코야끼 틀 = 클래스
- 만들어진 타코야끼 = 객체
클래스의 정의

클래스의 예
- 아래 정보를 기반으로 하는 플레이어 캐릭터 클래스 작성
- 속성 (변수, 데이터) : 플레이어 아이디, 체력
- 기능 (메소드) : 데미지를 입어 체력 감소

클래스의 문법

멤버 변수 (필드,Field)
- 클래스에 소속된 변수로 클래스의 속성을 저장, 사용하기 위한 용도
- 같은 클래스에 소속되어 있는 메소드는 이 변수를 조건 없이 사용 가능

멤버 함수 (메소드,Method)
- 클래스에 소속된 메소드로 클래스의 기능을 정의하고, 사용하기 위한 용도
- 같은 클래스에 소속되어 있는 메소드끼리는 조건 없이 호출 가능

접근 지정자
- 해당 멤버의 접근성을 설정하는 키워드
-
멤버 변수, 멤버 함수의 앞에 작성 (지역 변수는 사용 불가능)
- private, public, protected
- public : 외부에서 클래스를 통해 접근할 수 있다.
- private : 외부에서 접근할 수 없으며, 하위 클래스에서도 접근할 수 없다.
- protected : 외부에서 접근할 수 없으며, 하위 클래스에서는 접근할 수 있다.
- private는 default 지정자로 접근 지정자를 표기하지 않으면 private로 자동 설정
- Tip) 멤버 변수의 경우 특별한 경우에만 public을 사용하고, 그렇지 않을 경우는 private, protected를 지향
- Tip) internal, protected internal, private protected와 같은 접근 지정자도 있다.
접근 지정자의 사용 이유
- 객체 지향 프로그래밍을 할 때, 클래스에서 최소한의 기능만을 외부로 노출하고, 나머지는 감추는 것을 지향한다. (이를 클래스의 은닉성이라고 함)
-
현재 클래스 내부에서만 사용하는 기능의 경우 외부로 노출할 필요가 없다
- 예를 들어, TV를 사용할 때 리모컨을 조작해 TV 채널을 돌리고 즐겁게 TV를 시청하는 것이 사용자의 일이고,
-
실제로 화면에 어떻게 색이 표현되고, 소리가 어떤 원리로 나는지 몰라도 된다.
- 그래서 클래스 내에 있는 각 멤버(변수, 메소드)를 필요에 따라 외부에서 사용 가능하도록 하거나 사용할 수 없도록 설정하는 것이 접근지정자의 역할이다
클래스의 이용
- 클래스도 변수 데이터로 활용 가능 (int, float 등과 동일)
- 멤버 변수, 지역 변수, 매개 변수, 반환 값 등에 모두 사용 가능

클래스 객체 생성
- 클래스는 변수와는 다르게 선언만으로는 사용할 수 없다.
- new 키워드를 사용해 생성해야 사용 가능
- .을 사용해 해당 클래스의 멤버(변수, 메소드)에 접근 가능

null
- 사전적 의미는 존재하지 않는다는 뜻
- 초기화하지 않은 클래스의 default 값
- 가장 빈번하게 Exception을 일으키는 원인
- Exception : 실행 중에 발생하는 오류

생성자
- 객체가 생성될 때 자동으로 호출되는 메소드 (new로 메모리를 할당할 때)
- 생성자는 클래스 이름과 동일하게 정의

생성자 메소드 오버로딩

소멸자
- 객체가 소멸할 때 자동으로 호출되는 메소드 (가비지 컬렉터가 호출을 담당)
- 소멸자는 “~클래스 이름”과 같이 정의

얕은 복사

깊은 복사

this 키워드
- 클래스의 변수나 메소드에 접근할 때는 대상이 필요
- 클래스 내부에서 자기 자신의 변수나 메소드에 접근할 때 this 사용
- 변수 이름, 메소드 이름만 사용할 경우 default로 this가 자동 지정

정보 은닉
- 클래스 외부에서 클래스의 멤버 변수에 직접 접근하지 못하도록 멤버 변수를 private으로 선언하는 것(변수는 데이터를 저장 및 사용하기 때문에 직접 접근할 수 있도록 할 경우 들어가면 안되는 값을 넣어 오류가 발생할 수 있다)
캡슐화
- 정보은닉으로 인해 클래스 외부에서 접근 불가능한 멤버 변수의 값을 조작할 수 있도록 생성하는 멤버 함수
정보은닉과 캡슐화의 예

상속 (Inheritance)
- 유산 상속과 마찬가지로 유산을 물려주는 부모(기반) 클래스가 자신의 재산(public, protected 한정자로 정의된 변수와 메소드)을 유산을 상속 받는 자식(파생) 클래스에게 제공
상속을 하는 이유
- 여러 클래스에 동일하게 작성되는 내용은 부모 클래스로 작성한 후 자식 클래스가 상속 받아 사용하면 코드 간결화에 도움이 된다.
- 형식을 통일해 하나의 그룹(배열, 리스트 등)으로 관리할 수 있도록 한다. (업 캐스팅, 다형성 등의 추가적인 기법 필요)
상속의 예

base 키워드
- this 키워드가 자기 클래스 내부의 변수, 메소드에 접근할 때 사용하는 키워드라면 부모(기반) 클래스의 변수나 메소드에 접근할 때 사용하는 키워드가 base

상속 관계에서 생성자와 소멸자 호출 순서
- Entity(부모)의 생성자 -> Player(자식)의 생성자 -> Player(자식)의 소멸자 -> Entity(부모)의 소멸자

다형성 (Polymorphism)
- 다형성은 객체가 여러 가지 다양한 형태를 가지는 것을 뜻한다.
-
좀 더 정확하게는 상속을 받는 자식 클래스가 다양한 형태를 가지게 된다.
- 다형성의 첫 번째 과정 [업 캐스팅 (Up-Casting)]
- 부모 클래스의 참조 변수에 자식 클래스의 객체를 참조하는 것이 가능하다. (부모 클래스의 객체 변수에 자식 클래스 메모리 할당이 가능하다.)
- 부모 클래스와 자식 클래스 사이에 형 변환이 가능하다.

-
부모 클래스의 변수에 자식 클래스 메모리를 할당하는 업캐스팅은 가능하지만 , 자식 클래스 변수에 부모 클래스 메모리에 할당하는 다운캐스팅은 불가능합니다.
-
참조 변수 형식과 메모리 할당 형식에 따른 사용 가능 멤버 (변수, 메소드)

업캐스팅을 사용하는 이유?
- 형식을 통일하기 위해서 사용
- 플레이어가 다양한 종류의 적을 공격할 때
- 형식 통일이 필요한 이유는 ?
- 코드를 간결하게 하고, 코드의 수정을 최소화 하면서도 다양한 경우에 대비하기 위함 입니다.
- 또한, 형식이 통일되면 배열, 반복문 등을 이용해 동시에 작업을 시키는 것이 수월합니다.

업캐스팅을 활용한 형식 통일
-
플레이어가 다양한 종류의 적을 공격할 때

- 게임에 존재하는 다양한 적에게 같은 명령을 내릴 때

- 게임에 존재하는 다양한 적에게 같은 명령을 내릴 때

다형성의 두 번째 과정 [메소드 오버라이딩]
- 메소드 오버라이딩은 업 캐스팅으로 형식이 통일되었을 때 부모 클래스의 메소드가 아닌 자식 클래스의 메소드가 호출되도록 하는 것이다.

부모 클래스와 자식 클래스 사이의 형 변환

- 앞의 “case 03”과 같은 경우 컴파일할 때는 오류가 발생하지 않고, 프로그램을 실행했을 때 오류가 발생한다.
- 프로그램 실행 단계에서 형 변환이 가능한지, 형 변환에 성공했는지 확인하는 is와 as 연산자
- is 연산자 : 객체가 해당 형식에 해당하는지 검사한 후 그 결과를 bool 값으로 반환 (값, 참조 형식 모두 사용 가능)
- as 연산자 : 형식 변환 연산자와 같은 역할로 형 변환이 가능하면 형 변환을 해서 인스턴스를 반환하고, 형 변환에 실패하면 null을 반환한다. (참조 형식에만 사용 가능)
is, as 연산자 예

추상 클래스란?
- 추상 메소드(정의는 있지만 구현된 내용이 없는)를 포함하고 있는 미완성된 클래스
- 한정자, 반환 형식, 메소드 이름, 매개변수까지만 정의하고, 메소드가 호출되었을 때 어떤 행동을 하는지 내용이 없는 메소드

추상 메소드란?
- 한정자, 반환 형식, 메소드 이름, 매개변수까지만 정의하고 메소드가 호출되었을 때 어떤 행동을 하는지 내용이 없는 메소드

추상 클래스 특징
- new 연산자를 이용해 클래스 인스턴스를 생성할 수 없고, 추상 클래스를 상속 받은 자식 클래스에서만 구현 후 사용 가능
- 추상 메소드와 추상 프로퍼티를 정의할 수 있다.
추상 메소드 특징
- 추상 메소드는 추상 클래스에서만 정의할 수 있다.
- 추상 메소드의 접근 지정자는 public or protected 중 하나로 정의한다.
- 추상 메소드를 정의할 때 static, virtual을 사용할 수 없고, abstract 키워드를 사용해서 정의한다.
- 추상 메소드는 구현 내용이 없고, “이런 메소드를 사용할 것이다.”, “이런 메소드를 구현해야한다!” 라고 자식 클래스에게 구현을 강제하기 때문에 메소드 내용이 없고, 중괄호가 아닌 세미콜론(;)을 사용한다.
추상 클래스, 메소드 사용 이유
- 클래스를 상속 받는 자식 클래스가 메소드 오버라이딩을 사용할 때 자식 클래스에서 “무조건” 메소드를 구현하도록 하기 위해 사용
- 앞에서 배운 메소드 오버라이딩의 가상 메소드(virtual)는 자식 클래스에서 메소드를 구현하지 않아도 문제가 없기 때문에 강제성을 주기 위해 사용
추상 클래스의 예

댓글남기기