01/02 본캠프 #7

guno park·2024년 1월 2일
0

본캠프

목록 보기
7/77

강의 정리

4주차

인터페이스와 열거형

인터페이스

  • 다중 상속을 사용하지 않는 이유
  1. 다이아몬드 문제
    한 클래스가 두 개 이상의 부모 클래스로부터 동일한 멤버를 상속 받을 수 있음.
  2. 설계의 복잡성 증가
  3. 이름 충돌과 충돌 해결의 어려움
  4. 설계의 일관성과 단순성 유지
  • 인터페이스를 사용하는 이유
  1. 코드의 재사용성
    인터페이스를 사용하면 다른 클래스에서 해당 인터페이스를 구현하여 동일한 기능을 공유
  2. 다중상속 제공
  3. 유연한 설계
    클래스와 인터페이스 간에 느슨한 결합
  • 특징
  1. 클래스가 구현해야 하는 멤버들을 정의하는 것
  2. 인터페이스는 클래스의 일종이 아니며, 클래스에 대한 제약 조건을 명시하는 것
  3. 클래스가 인터페이스를 구현할 경우, 모든 인터페이스 멤버를 구현해야함.
  4. 인터페이스는 다중 상속을 지원함
  • 인터페이스 구현
    interface 키워드로 구현
    이름은 I로 시작
iterface ImyInterface
{
  void Method1();
  int Method2(string str);
}
namespace Week4
{
    internal class Class1
    {
        public interface IUsable
        {
            void Use();
        }

        public class Item : IUsable
        {
            public string Name { get; set; }

            public void Use()
            {
                Console.WriteLine("아이템 {0}을 사용했습니다.", Name);
            }
        }
        public class Player
        {
            public void UseItem(IUsable item)
            {
                item.Use();
            }
        }

        static void Main(string[] args)
        {
            Player player = new Player();
            Item item = new Item() { Name = "Heath Position" }; //중괄호 넣어서 지정해줄 수 있음.
            player.UseItem(item);
        }
    }
}
  • 인터페이스 사용 이유
    ex) 우리가 아이템이라는게 iusable 상속받았기 떄문에 사용할 수 있었는데
    소모성 아이템 / 장착 아이템 등등 종류가 많은데 그걸 전부다 하나의 클래스가 아니라
    다양한 클래스로 구현하게 될텐데 거기서 인터페이스를 상속하게 되면 use함수를 그냥 사용할 수 있다.

  • 다중 상속 구현 예제

namespace Week4
{
    internal class Class2
    {
        //다중 상속 구현 예제
        public interface IItemPickable
        {
            void PickUp();
        }

        public interface IDroppalbe
        {
            void Drop();
        }

        public class Item : IItemPickable, IDroppalbe
        {
            public string Name { get; set; }

            public void PickUp()
            {
                Console.WriteLine("아이템 {0}을 주웠습니다.", Name);
            }
            public void Drop()
            {
                Console.WriteLine("아이템 {0}을 버렸습니다.", Name);
            }
        }

        public class Player
        {
            public void InteractWithItem(IItemPickable item)
            {
                item.PickUp();
            }

            public void DropItem(IDroppalbe item)
            {
                item.Drop();
            }
        }

        static void Main(string[] args)
        {
            Player player = new Player();
            Item item = new Item { Name = "Sword" };

            //아이템 주울 수 있음
            player.InteractWithItem(item);

            //아이템 버릴 수 있음
            player.DropItem(item);
        }
    }
}

인터페이스 vs 추상클래스

  • 인터페이스는 추상적인 동작만 정의하고 구현을 갖지 않음 = 동작 내용이 없음
  • 다중 상속이 가능

추상 클래스의 특징과 장단점

  • 추상클래스는 일부 동작의 구현을 가지며, 추상 메서드를 포함할 수 있음
  • 단일 상속만 가능, 다른 클래스와 함께 상속 계층 구조를 형성 가능

내가 생각하는 인터페이스 : 추상클래스

  • 활용도 - 같은 클래스이지만 수행하는 동작이 다를 때 사용 / 특정 오브젝트들이 동일한 동작을 수행해야할때(내용은 다르게 할 수 있음)
  • 장점 : Class : interface 이렇게 선언하는거라 다중상속도 되고 사용하기 편한거 같음 / override 써야됨.
  • 주의 : 인터페이스는 매개변수, 반환 타입이 인터페이스 타입임. 상속된 클래스가 아니라 인터페이스를 써야됨.

Enums 열거형

  • 사용하는 이유
  1. 가독성 - 일련의 연관된 상수들을 명명할 수 있음.
  2. 자기 문서화 - 의미 있는 이름을 사용하여 상수를 명명할 수 있음.
  3. 스위치 문과의 호환성 - 열거형은 스위치 문과 함께 사용될 때 유용함.
  • 특징
  1. 서로 관련된 상수들의 집합을 정의할 때 사용됨
  2. 정수값만 사용됨

※ enum 선언하고 맨위에꺼에 상수 값 지정해주면 그 밑에서는 +1되서 자동으로 인덱싱됨

  • 자주 사용되는 사례
  1. 게임 상태 - 메인메뉴 / 플레잉 / 일시정지 /게임오버
  2. 방향
  3. 아이템 등급

예외처리 및 값형과 참조형

예외처리

예외란? 프로그램 실행 중 발생하는 예기치 않은 상황

예외처리의 필요성과 장점

  • 예외 상황에 대비하여 프로그램을 안정적으로 유지하는데 도움을 줌
  • 예외 처리를 통해 오류 상황을 적절히 처리하고 프로그램의 실행을 계속할 수 있다.
  • 프로그램의 안정성을 높이고 디버깅을 용이하게함

예외처리 구현
try-catch

try
{
//예외가 발생할 수 있는 코드
}
catch (ExceptionType1 ex)
{
//ExceptionType1에 해당하는 예외 처리
}
catch (ExceptionType2 ex)
{
//ExceptionType2에 해당하는 예외 처리
}
finally
{
//예외 발생 여부와 상관없이 항상 실행되는 코드
}

catch는 위에서부터 순서대로 실행, 상속관계에 있는 경우 상위 예외 타입이 먼저 실행됨

예외 객체
ExceptionType 이 매개변수 안에 이 예외처리에 발생한 여러가지 정보들, 오류메세지들이 내포되어있음.

  • finally 블록은 예외 발생 여부와 상관없이 항상 실행
  • 예외 발생시 정리 작업이나, 리소스 해제 등의 코드를 포함
  • 생략 가능

실행 시점
예외가 발생한 경우 : 예외 처리과정을 다 거친후 실행
않은 경우 : 정상 실행

try
{
    int result = 10 / 0;  // ArithmeticException 발생
    Console.WriteLine("결과: " + result);
}
catch (DivideByZeroException ex)
{
    Console.WriteLine("0으로 나눌 수 없습니다.");
}
catch (Exception ex)
{
    Console.WriteLine("예외가 발생했습니다: " + ex.Message);
}
finally
{
    Console.WriteLine("finally 블록이 실행되었습니다.");
}

사용자 정의 예외
사용자 정의 예외 클래스 작성

  • 사용자는 필요에 따라 자신만의 예외 클래스를 작성할 수 있습니다.
  • 사용자 정의 예외 클래스는 Exception 클래스를 상속받아 작성하며, 추가적인 기능이나 정보를 제공할 수 있습니다.
public class NegativeNumberException : Exception
{
    public NegativeNumberException(string message) : base(message)
    {
    }
}

try
{
    int number = -10;
    if (number < 0)
    {
        throw new NegativeNumberException("음수는 처리할 수 없습니다.");
    }
}
catch (NegativeNumberException ex)
{
    Console.WriteLine(ex.Message);
}
catch (Exception ex)
{
    Console.WriteLine("예외가 발생했습니다: " + ex.Message);
}
---------------------------------------------------------------
// 플레이어 이동
try
{
    // 플레이어 이동 코드
    if (IsPlayerCollidingWithWall())
    {
        throw new CollisionException("플레이어가 벽에 충돌했습니다!");
    }
}
catch (CollisionException ex)
{
    // 충돌 예외 처리
    Debug.Log(ex.Message);
    // 예외에 대한 추가 처리
}


// 리소스 로딩
try
{
    // 리소스 로딩 코드
    LoadResource("image.png");
}
catch (ResourceNotFoundException ex)
{
    // 리소스가 없는 경우 예외 처리
    Debug.Log(ex.Message);
    // 예외에 대한 추가 처리
}
catch (ResourceLoadException ex)
{
    // 리소스 로딩 중 오류가 발생한 경우 예외 처리
    Debug.Log(ex.Message);
    // 예외에 대한 추가 처리
}


// 게임 상태 전이
try
{
    // 상태 전이 코드
    if (currentGameState != GameState.Playing)
    {
        throw new InvalidStateException("게임이 실행 중이 아닙니다!");
    }
    // 게임 상태 전이 실행
}
catch (InvalidStateException ex)
{
    // 상태 예외 처리
    Debug.Log(ex.Message);
    // 예외에 대한 추가 처리
}

throw = 일부러 에러 발생시킬 때 쓰는거

모든 부분에 작성하진 않지만 우려가 되는 부분에 사용한다.
예외처리는 길게 작성하면 오히려 어려워진다.
구체적인 예외 클래스를 사용하면좋음

값형과 참조형

박싱과 언박싱
박싱 = 값 -> 참조형 / 값형이 사라지는게 아니라 참조형이 새롭게 만들어지는거 > 독립된 값
언박싱 = (박싱된 객체) ->값형

기본 예제

class Program
{
    static void Main()
    {
        // 값형
        int x = 10;
        int y = x;
        y = 20;
        Console.WriteLine("x: " + x); // 출력 결과: 10
        Console.WriteLine("y: " + y); // 출력 결과: 20
        // 참조형
        int[] arr1 = new int[] { 1, 2, 3 };
        int[] arr2 = arr1;
        arr2[0] = 4;
        Console.WriteLine("arr1[0]: " + arr1[0]); // 출력 결과: 4
        Console.WriteLine("arr2[0]: " + arr2[0]); // 출력 결과: 4
        // 박싱과 언박싱
        int num1 = 10;
        object obj = num1; // 박싱
        int num2 = (int)obj; // 언박싱
        Console.WriteLine("num1: " + num1); // 출력 결과: 10
        Console.WriteLine("num2: " + num2); // 출력 결과: 10
    }
}

리스트 활용 예제

List<object> myList = new List<object>();
// 박싱: 값 형식을 참조 형식으로 변환하여 리스트에 추가
int intValue = 10;
myList.Add(intValue); // int를 object로 박싱하여 추가
float floatValue = 3.14f;
myList.Add(floatValue); // float를 object로 박싱하여 추가
// 언박싱: 참조 형식을 값 형식으로 변환하여 사용
int value1 = (int)myList[0]; // object를 int로 언박싱
float value2 = (float)myList[1]; // object를 float로 언박싱

델리게이트,람다,링큐

  • 델리게이트(delegate)는 메서드를 참조하는 타입입니다.
  • 델리게이트를 이용하면 메서드를 매개변수로 전달하거나 변수에 할당할 수 있습니다.

왜 쓰느냐
메서드에 직접 접근이 좀 불편할때 씀

등록하기

delegate int Calculate(int x, int y);

static int Add(int x, int y)
{
    return x + y;
}

class Program
{
    static void Main()
    {
        // 메서드 등록
        Calculate calc = Add;

        // 델리게이트 사용
        int result = calc(3, 5);
        Console.WriteLine("결과: " + result);
    }
}
----------------------------------------------------------------------------
//하나 이상의 메서드 등록하기
delegate void MyDelegate(string message);

static void Method1(string message)
{
    Console.WriteLine("Method1: " + message);
}

static void Method2(string message)
{
    Console.WriteLine("Method2: " + message);
}

class Program
{
    static void Main()
    {
        // 델리게이트 인스턴스 생성 및 메서드 등록
        MyDelegate myDelegate = Method1;
        myDelegate += Method2;

        // 델리게이트 호출
        myDelegate("Hello!");

        Console.ReadKey();
    }
}
// 델리게이트 선언
public delegate void EnemyAttackHandler(float damage);
// 적 클래스
public class Enemy
{
    // 공격 이벤트
    public event EnemyAttackHandler OnAttack;
    // 적의 공격 메서드
    public void Attack(float damage)
    {
        // 이벤트 호출
        OnAttack?.Invoke(damage);
				// null 조건부 연산자
				// null 참조가 아닌 경우에만 멤버에 접근하거나 메서드를 호출
    }
}
// 플레이어 클래스
public class Player
{
    // 플레이어가 받은 데미지 처리 메서드
    public void HandleDamage(float damage)
    {
        // 플레이어의 체력 감소 등의 처리 로직
        Console.WriteLine("플레이어가 {0}의 데미지를 입었습니다.", damage);
    }
}
// 게임 실행
static void Main()
{
    // 적 객체 생성
    Enemy enemy = new Enemy();
    // 플레이어 객체 생성
    Player player = new Player();
    // 플레이어의 데미지 처리 메서드를 적의 공격 이벤트에 추가
    enemy.OnAttack += player.HandleDamage;
    // 적의 공격
    enemy.Attack(10.0f);
}

이 부분 알아두면 많이 쓸거 같으니까 다시 보기

  • (OnAttack?.Invoke(damage);)
    여기서 ?란
    null 조건부 연산자
    null 참조가 아닌 경우에만 멤버에 접근하거나 메서드를 호출

람다 - 익명메서드

참조만을 가지고 컨트롤해야됨.

구현 - 좀 신기하게 생김

(parameter_list) => expression

Calculate cacl = (x,y) ->
{
return x+y;
};

람다를 사용할때는 델리게이트가 꼭 함께나옴

기능이 확장된다면 메서드로 빼주는게 좋지만
간단한 메서드일 경우 람다로 처리하는것도 깔끔함

Func와 Action

델리게이트를 대체하는 미리 정의된 제네릭 형식
Func는 값을 반환하는 메서드를 나타내는 델리게이드
ex) Func<int,string>은 int를 입력받아 string을 반환
Action은 값을 반환하지 않는 메서드 / 매개변수를 받아들이지만 반환타입은 없음

func및action은 제네릭 형식으로 미리 정의되어 있어 매개변수와 반환타입을 간결하게 표현할 수 있음.

예시

// 게임 캐릭터 클래스
class GameCharacter
{
    private Action<float> healthChangedCallback;

    private float health;

    public float Health
    {
        get { return health; }
        set
        {
            health = value;
            healthChangedCallback?.Invoke(health);
        }
    }

    public void SetHealthChangedCallback(Action<float> callback)
    {
        healthChangedCallback = callback;
    }
}

// 게임 캐릭터 생성 및 상태 변경 감지
GameCharacter character = new GameCharacter();
character.SetHealthChangedCallback(health =>
{
    if (health <= 0)
    {
        Console.WriteLine("캐릭터 사망!");
    }
});

// 캐릭터의 체력 변경
character.Health = 0;

예시중에 피가 닳 때마다 호출 callback 이란걸 많이 씀
이 부분 쓰는 이유 : HP UI, HP가 떨어졌을때 빨간화면이 나오는것도 걸어놓을수있고 HP 관련된 함수들을 전부 걸어놓으면 자동으로 HP가 변화를 가질때마다 Callback됨

linq

  • var 키워드는 결과 값의 자료형을 자동으로 추론합니다.
  • from 절에서는 데이터 소스를 지정합니다.
  • where 절은 선택적으로 사용하며, 조건식을 지정하여 데이터를 필터링합니다.
  • orderby 절은 선택적으로 사용하며, 정렬 방식을 지정합니다.
  • select 절은 선택적으로 사용하며, 조회할 데이터를 지정합니다.
    List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
    // 쿼리 작성 (선언적인 구문)
    var evenNumbers = from num in numbers
                    where num % 2 == 0
                    select num;
    // 쿼리 실행 및 결과 처리
    foreach (var num in evenNumbers)
    {
      Console.WriteLine(num);
    }

고급 자료형 및 기능

Nullable
Null?

  • 아무것도 없음을 의미
  • 참조형 변수가 어떠한 객체를 참조하지 않을 때 사용

Nullable?

  • null 값을 가질 수 있는 값형에 대한 특별한 형식
  • 값형 변수에 null값을 지정 할 수 있는 방법을 제공
  • 형식은 ? 연산자를 사용하여 선언됨.

ex) int?는 int형식에 null을 할당할 수 있는 Nullable를 나타냄

// Nullable 형식 변수 선언
int? nullableInt = null;
double? nullableDouble = 3.14;
bool? nullableBool = true;

// 값 할당 및 접근
nullableInt = 10;
int intValue = nullableInt.Value;

// null 값 검사
if (nullableDouble.HasValue)
{
  Console.WriteLine("nullableDouble 값: " + nullableDouble.Value);
}
else
{
  Console.WriteLine("nullableDouble은 null입니다.");
}

// null 병합 연산자 사용
// nullableInt ?? 0과 같이 사용되며, nullableInt가 null이면 0을 반환합니다.
int nonNullableInt = nullableInt ?? 0;
Console.WriteLine("nonNullableInt 값: " + nonNullableInt);

HasValue 값이 세팅된적 있는지 없는지로 bool로 반환됨.

문자열 빌더

  1. 문자열 조작
    Append(),Insert(),Replace(),Remove();
  2. 가변성
    내부 버퍼를 사용하여 문자열 조작을 수행하므로 크기를 동적으로 조정할 수 있음.
    따라서 문자열의 크기가 늘거나 줄어도 추가적인 메모리 할당이 발생하지 않음.
  3. 효율적인 메모리 관리
    문자열 조작 시 내부 버퍼를 사용하여 문자열을 조작하므로, 반복적인 문자열 조작 작업이 발생해도 메모리 할당 및 해제 오버헤드가 크게 감소합니다.
    문자열을 계속 더하거나 빼야되는 경우에는 스트링빌더를 사용하는걸 추천함

특강 정리

학습법 특강
특강 제목 : Not Coder, Be Developer
어떻게하면 '진짜' 개발자가 될 수 있을까?
내가 단기간 바짝 공부해서 성공적으로 취업 할 수 있을까?

할 수 있다. 다만 쉽지 않다.
본인의 노력이 수반되어야 한다.

  1. 내배캠 커리큘럼

1) 습관화 : 나의 자산을 만들기 - TIL, WIL, 알고리즘
1 문제를 해결하기 위한 방안으로 어떤 것들을 생각했고, 어떤 것들을 선택 했는지, 또 그 선택이 옳은 선택인지 아닌지 기록해둘수있다.
2 채용자 입장에서 봤을 때도 면접자의 강점으로 작용한다. (문제 해결능력, 꾸준함) > 꾸준하게 작성하자.

2) 배운 내용 복습하며 사고력과 구현력 중점적으로 단련 - 개인과제, 팀과제

3) 기술적 의사결정, 기술적 고민을 동시에 - 프로젝트
본인만의 문제해결 능력이 나와야됨.
나는 어떤 프로젝트를 진행하려고했고, 어떤 부분을 구현하기 위해 이러이러한 고민을 했습니다.

이 선택에 대해 여러 고민과 합리적인 선택임을 어필 할 수 있어야됨 = 기술적 의사결정 + 고민 이라는것 / 프로젝트 기간 중 많이 길러야하는 부분

4) 메타인지, 수료 때까지 도달해야하는 실력 목표 - 개발역량점검표

기본기가 탄탄한 주니어 개발자를 안 데려갈 곳은 없다

  1. 코더가 아닌 개발자 되는 법
    강의를 열심히 듣기만 하면 개발자 될 수 있을까요?
    과제나 프로젝트에서 어려운 기술이나 다양한 스택을 사용하면 취업 잘될까요?
    코딩 배우러 왔는데 기술적으로 잘 구현하는 것이 제일 중요한거 아닐까요?
    답은 NO 잘하는 건 선배 개발자들이 더 잘한다.

왜 기술적인 요구사항이 아닌 자질이나 성향을 보는걸까요?
성장 가능성이 높은 사람 / 다른 사람과 협업하며 좋은 결과를 이끌어낼 수 있는 사람
자신의 성장뿐만 아니라 동료들과 함께 성장할 사람 / 끊임없는 고민으로 좋은 프로적트를 만들어낼 사람
중요한건 협업과 기술적 고민
기술적 고민을 잘하려면

  • 로직과 코드에 대한 의도를 생각하기
  • 구현하는 기술,스택에 목적과 근거 가지기 - 개발에 그냥은 없음, 항상 목적과 근거가 있어야함.
  • 더 좋은 방법이 있는지 고민하기 - 항상 의심하기 (이게 최선일까)

협업을 잘하려면

  • 예쁘게 말하기
  • 전달하고자 하는 바를 명확하게 말하기 + 간결하게
  • 데이터 또는 기술적인 근거를 바탕으로 소통하기
    옳은 말을 기분 좋게 하라, 당해낼 자가 없다.
  1. 내배캠 9to9 활용법
    4개월간 몰입해서 압축성장하려면 시간을 어떻게 할애하면 좋을까?
    point 1. 가만히 팔짱끼고 반복적으로 강의만 듣거 보고 따라치기만 하는 것은 절대 도움이 되지 않음
  • 원격 강의 : 개념과 구조 이해 > 이해한 부분 직접 구현하기
  • 실시간 강의 : 완전히 이해하지 못하더라도 집중해서 듣기 > 녹화본으로 복습하기
  • 과제 : 과제의 목적은 배운 내용 복습 및 구현 연습, 완성하지 못했더라도 피드백을 받고 부족한 부분 채우기

질문과 공유는 필수 덕목
질문 : 1.문제정의 - 2. 해결방안 (어떤걸 생각 했는지)
공유 : 답변받은 좋은 내용이 있다면 주변에도 공유하기

집중코딩시간에는 몰입해서 코딩만 해주세요.

Chatgpt를 어떤 상황에서 써야 적절하게 썼다고 할 수 있을까요?
1.코드의 뼈대를 만들어봅니다.
2. 뼈대와 뼈대를 이어붙일 경우 구조와 흐름을 생각하여 어떻게 연결시킬지 고민해봅니다.
3. 중심이 되는 코드는 직접 고민하여 코드를 작성합니다.
4. 완성된 코드가 그대로 공유되어도 될지 충분히 검토해보고 고민해봅니다.
사용하더라도 이게 어떻게 동작하는지 이해하고 넘어가아된다.

  1. 최하방에서 최우수 프로젝트 팀장까지
    내 실력이 부족한 것을 자책하기 보단 어떤 부분을 채워야하고 집중해야 하는지 판단하고 실행하는 것이 더 중요
    해결이 어려운 문제가 생기면 적극적으로 동기들에게 질문하고 함께 해결

고민이 있을 때, 혼자 낙담하지 않고 튜터 또는 매니저에게 상담 요청

어떻게 하면 유저 입장에서 더 좋은 서비스를 개발할 수 있을지 계속 고민

중꺾마 - 중요한 건 꺾였는데도 그냥 하는 마음

오늘의 질문내용

대답해주신 튜터님 - 김주안 튜터님

질문 1. Swich문으로 Method를 반복 실행되게 만들었는데 문제가 없는가?
대답 - while문처럼 연산 횟수가 확 늘어나는게 아닌 이상 정상적으로 동작되는게 갑자기 터질 일은 드물다. 게임 플레이 시간과 상관 없이 이 연산을 몇번이나 반복했느냐가 중요하다.

여담 - 데이터 저장 한 부분에 Json 썼다고 말씀드리고 어떤건지 여쭤보니까 정확하게 뭔지는 듣지 못했지만 파싱하는거부터 익히고 또 다음 공부할 스텝을 알려주셨다.
그리고 동기화 / 비동기화에 관한 얘기도 해주셔서 그것도 공부해 볼 예정이다.

내일 일정

강의 5주차 마저 완강
다음으로 뭘로 빠질지 모르겠는데
1. 주차별 과제 해보기
2. 고급 문법 + 알고리즘 부분 다시 복습
3. 튜터님이 추천해주신 내용 공부해보기
이건 내일 끌리는걸로 할 예정

0개의 댓글