[공부] 261015 복습 / 인덱서 / Interface 무기장착

강현구
∙∙조회 6

[이론]

추상화: 복잡한 현실의 몯느 세부사항을 생략하고 문제해결에 필요한 요소와 기능만을 담는것

 

클래스: 객체를 생성하기 위한 설계도

이 자체로는 동작하지 않고 이를 통해 변수를 만들고 값을 할당해야함

 

객체: 클래스를 기반으로 만들어진 실제 데이터와 동작의 결합체


추상클래스: 세부적은 구현은 자식에게 맡기고 본인은 최소한의 기능만 가지는 클래스



[인덱서(Indexer) ← 얜 대체 뭐야]

인덱서(Indexer) ← 배열도 아닌데 왜 []를 쓰지?

인덱서: 객체에 []로 값을 요청할 수 있도록 만드는 기능

  • 배열처럼 보이지만, 실제 배열일 필요는 없음
  • obj[2]를 호출하면 C#이 해당 객체에 선언된 인덱서를 찾아 실행함
  • 인덱서는 값을 저장하는 공간이 아니라, 값을 요청받았을 때 어떻게 반환할지 정하는 기능
  • 메서드처럼 값을 반환할 수 있지만, 호출 문법이 다름
csharp
// 인덱서 선언
public int this[int index]
{
    get { return index * 10; }
}

// 호출
int number = obj[2]; // index에 2가 전달됨 → 20 반환


인덱서는 this[int index] ← 왜 이름이 없지?

this는 인덱서를 선언할 때 사용하는 특별한 문법

  • int는 인덱서가 반환할 값의 자료형
  • index는 대괄호 안에서 전달받을 값을 담는 매개변수
  • 인덱서 자체에는 Count 같은 별도의 이름을 붙이지 않음. 객체에 obj[번호] 형태로 접근하기 때문
  • Count 같은 다른 프로퍼티가 없어도 인덱서만 따로 만들 수 있음
csharp
public int this[int index]
{
    get { return index * 10; }
}


인덱서는 여러 개 만들 수 있나?

한 클래스 안에 여러 인덱서를 선언할 수 있음

  • 매개변수의 자료형이나 개수 등으로 구분할 수 있어야 함
  • 반환형만 다르게 선언하는 것은 불가능
csharp
// 인덱서 선언
public int this[int index]
{
    get { return index * 10; }
}

// 호출
int number = obj[2]; // index에 2가 전달됨 → 20 반환

//////////////////

obj[2];       // int를 받는 인덱서
obj["안녕"];  // string을 받는 인덱서

 


배열 vs

배열 vs 인덱서

배열은 실제 저장된 값을 읽고, 인덱서는 정의된 동작을 실행한다.

  • 배열: arr[1] → 배열의 1번 위치에 저장된 값
  • 인덱서: obj[2] → 인덱서의 get 실행 결과
csharp
// 배열: 실제 저장된 값 읽기
int[] arr = { 10, 20, 30 };
int number = arr[1]; // 20

// 인덱서: get의 계산 결과 반환
int number2 = obj[2]; // index * 10 → 20

인덱서 vs 메서드

둘 다 값을 반환할 수 있다. 차이는 주로 호출하는 문법과 용도다.

  • 메서드: 작업이나 동작을 실행할 때 사용
  • 인덱서: 객체의 값을 인덱스나 키로 조회·설정하는 형태에 적합
  • 인덱서는 필수가 아님. 메서드로 구현해도 되는 경우가 많음
  • 단, 인터페이스가 인덱서를 요구한다면 구현 클래스도 해당 인덱서를 구현해야 함
csharp
// 메서드
obj.GetValue(2);

// 인덱서
obj[2];



[Interface 무기 장착]

csharp
using System;

namespace ConsoleApp1
{
    interface IAttackable
    {
        void Attack();
    }

    internal class InterWeapon
    {


        private IAttackable? _weapon = null;

        class Sword : IAttackable
        {
            public void Attack()
            {
                Console.WriteLine("검 공격");
            }
        }

        class Gun : IAttackable
        {
            public void Attack()
            {
                Console.WriteLine("총 공격");
            }
        }

        class Staff : IAttackable
        {
            public void Attack()
            {
                Console.WriteLine("지팡이 공격");
            }
        }

        public void Equipment(IAttackable weapon)
        {
            _weapon = weapon;
            Console.WriteLine("무기를 장착했습니다.");
        }

        public void Attack()
        {
            if (_weapon == null)
            {
                Console.WriteLine("먼저 무기를 장착하세요.");
                return;
            }

            _weapon.Attack();
        }

        static void Main(string[] args)
        {
            InterWeapon player = new InterWeapon();

            Console.WriteLine("무기 선택: 1. 검 / 2. 총 / 3. 지팡이");
            int wNum = int.Parse(Console.ReadLine());

            switch (wNum)
            {
                case 1:
                    player.Equipment(new Sword());
                    break;
                case 2:
                    player.Equipment(new Gun());
                    break;
                case 3:
                    player.Equipment(new Staff());
                    break;
                default:
                    Console.WriteLine("잘못된 무기 번호입니다.");
                    return;
            }

            Console.WriteLine("Enter를 누르면 공격합니다.");
            Console.ReadLine();

            player.Attack();
        }
    }
}
  • interface IAttackable 선언
  • private IAttackable? _weapon = null;
    • IAttackable? : null일 수도 있다고 타입에 표시
    • = null : 선언하는 순간 실제 초기값을 null로 지정
  • class Sword : IAttackable들 인터페이스 구현
  • public void Equipment(IAttackable weapon)
    • 매개변수로 무기타입을 받음
    • weapon = weapon; - 위에서 _weapon이걸 인터페이스 담는 공간으로 선언해서 무기 정보 받음
  • _weapon.Attack(); 공격 실행 지금 무기에 담긴 공격 실행함
  • InterWeapon player = new InterWeapon();

    InterWeapon

    변수에 담을 객체의 타입

    player

    변수 이름

    new InterWeapon()

    InterWeapon 객체를 생성

    왜 객체를 생성하냐면, 네가 작성한 `Equipment()`와 `Attack()`은 `static`이 없는 인스턴스 메서드이기 때문이야. 즉, 특정 `InterWeapon` 객체를 대상으로 무기를 장착하고 공격하도록 만든 거야. 예를 들어 플레이어 객체를 두 개 만들 수도 있어.

 

코드의미
player메서드를 실행할 객체
.Equipment(...)그 객체의 Equipment() 메서드를 호출
new Sword()새 검 객체를 생성해서 인자로 전달

실행 순서는 다음과 같아.

new Sword()

검 객체 생성

player.Equipment(검 객체)

player의 메서드에 검 객체 전달

_weapon = weapon;

player가 사용하는 무기로 연결