[22회차 수업내용]
1. 오버로딩
2. 상속
3. 가상화, 추상화
4. 인터페이스
주로 지난 내용의 복습/실습으로 이루어졌다.
2025.06.13 - [프로그래밍/유니티 부트캠프] - 유니티(형변환,객체지향프로그래밍) _ 멋쟁이사자처럼 유니티 부트캠프 후기 21회차
1. 오버로딩
- 메서드 이름은 같고, 매개변수(타입, 개수)가 다른 것
- 목적: 같은 동작을 상황에 따라 다양하게 처리
public class StudyOverloading : MonoBehaviour
{
void Start()
{
Attack();
Attack(true);
Attack(10f);
Attack(10, new GameObject("몬스터"));
}
public void Attack()
{
Debug.Log("공격");
}
public void Attack(bool isMagic)
{
if (isMagic)
Debug.Log("마법 공격");
}
public void Attack(float damage)
{
Debug.Log($"{damage} 데미지 만큼 공격");
}
public void Attack(float damage, GameObject target)
{
Debug.Log($"{target.name}에게 {damage} 데미지 만큼 공격");
}
}
[코드 입력 결과]
공격
마법 공격
10 데미지 만큼 공격
몬스터에게 10 데미지 만큼 공격
2. 상속
부모 클래스(기본 클래스)의 속성과 메서드(기능)를 자식 클래스(파생 클래스)가 물려받아 사용
- 중복 제거 → 코드 재사용
- 공통 기능 통합 관리 → 유지보수 편함
- 확장성 → 자식 클래스가 고유 기능 추가 가능
* 상속 적용 예시
//person 안에 Student와 Soldier 공통기능은 함께 + 타입별 기능은 각자 = 코드 효율성 증가
public class Person : MonoBehaviour
{
public string name;
public int age;
public void Walk()
{
Debug.Log("Walk");
}
public void Run()
{
Debug.Log("Run");
}
}
//사람
public class Student : Person
{
public string schoolName;
public string classNumber;
public void Study()
{
Debug.Log("Study");
}
}
//솔져
public class Soldier : Person
{
public string soldierNumber;
public void Shoot()
{
Debug.Log("Shoot");
}
}
[persons 상속 예시]
public class StudyInheritance : MonoBehaviour
{
// Person을 상속한 Student, Soldier 객체들을 저장하는 리스트
public List<Person> persons = new List<Person>();
void Start()
{
// Student와 Soldier 객체 각각 10개씩 생성하여 persons 리스트에 추가
for (int i = 0; i < 10; i++)
{
Student student = new Student(); // 학생 객체 생성
persons.Add(student); // 리스트에 추가
Soldier soldier = new Soldier(); // 군인 객체 생성
persons.Add(soldier); // 리스트에 추가
}
}
public void AllMove()
{
// persons 리스트에 있는 모든 객체에게 Walk() 호출
// Student, Soldier 구분 없이 부모(Person)의 기능으로 처리
foreach (var person in persons)
person.Walk();
}
}
*리마인드
- .Add() :리스트에 새 요소 추가하는 함수
- foreach (var 변수 in 컬렉션) → 컬렉션의 요소들을 하나씩 꺼내서 순서대로 반복 실행하는 구문
3. 가상화/추상화
[Character 상속 예시]
public abstract class Character : MonoBehaviour
{
public float hp;
public float moveSpeed;
void Update()
{
Move();
}
// 가상 메서드: 필요 시 자식 클래스에서 오버라이드 가능
public virtual void Attack()
{
Debug.Log("공격1");
}
// 추상 메서드: 반드시 자식 클래스에서 구현해야 함
public abstract void Move();
}
Attack과 Move를 재정의한 자식 클래스
// Character 클래스를 상속받는 Player 클래스
public class Player : Character
{
public override void Attack() // Attack 메서드 오버라이드 (재정의)
{
base.Attack(); // 부모 클래스(Character)의 Attack() 먼저 실행 → "공격1" 출력
Debug.Log("Player 공격"); // 이후 Player 고유 공격 동작 출력
}
// 반드시 구현해야 하는 추상 메서드 Move() → Player 클래스 전용 이동 동작 정의
public override void Move()
{
Debug.Log("Player 이동"); // "Player 이동" 출력
}
}
| base.메서드() | 부모 클래스의 메서드를 그대로 호출 → 기본 동작 유지 + 추가 동작 덧붙이기에 사용 |
[이어폰 예시]
public class EarPhone : MonoBehaviour
{
// 이어폰 이름 (예: Galaxy Buds, AirPods 등)
public string name;
// 이어폰 가격
public float price;
// 출시 연도
public int releaseYear;
// 음악 재생 기능 메서드
public void PlayMusic()
{
Debug.Log("음악 재생"); // 콘솔에 "음악 재생" 출력
}
}
// WireEarPhone 클래스는 EarPhone 클래스를 '상속'받음 → EarPhone의 변수와 메서드 사용 가능
public class WireEarPhone : EarPhone
{
void Start()
{
// 상속받은 name, price, releaseYear 변수에 값 할당
name = "EarPod";
price = 30f;
releaseYear = 2005;
}
}
// WirelessEarPhone 클래스는 EarPhone 클래스를 '상속'받음 → EarPhone의 변수와 메서드 사용 가능
public class WirelessEarPhone : EarPhone
{
public float batterySize; // 배터리 용량 (예: 70f)
public bool isWirelessCharged; // 무선 충전 지원 여부 (true/false)
void Start()
{
name = "AirPod1"; // 상속받은 변수 초기화
price = 100f;
releaseYear = 2007;
batterySize = 70f; // 새로운 멤버 변수 값 설정
}
// 충전 방식 출력하는 메서드
public void Charged()
{
// 삼항 연산자 사용: isWirelessCharged가 true면 "무선 충전", false면 "유선 충전"왜 ms
string msg = isWirelessCharged ? "무선 충전" : "유선 충전";
Debug.Log(msg);
}
}
(msg -> message)
4. 인터페이스
4.1 인터페이스 생성 예시
public interface IDamageable
{
void TakeDamage(float damage);
void Death();
}
//공격 불가능한 wall 클래스
public class Wall : MonoBehaviour
{
}
//공격 가능한 Door 클래스
public class Door : MonoBehaviour, IDamageable
{
public float hp = 100f;
public void TakeDamage(float damage)
{
Debug.Log($"{damage}만큼의 피해를 입었습니다.");
hp -= damage;
if (hp <= 0f)
Death();
}
public void Death()
{
Debug.Log("문이 파괴되었습니다.");
}
}
Trigger 감지 _ 공격하는 Sword
public class Sword : MonoBehaviour
{
public float damage = 10f;
private void OnTriggerEnter(Collider other)
{
// 충돌한 대상이 IDamageable 인터페이스를 구현하고 있는지 확인
if (other.GetComponent<IDamageable>() != null)
{
// 대상에게 데미지를 입히기 위해 TakeDamage 함수 호출
other.GetComponent<IDamageable>().TakeDamage(damage);
}
}
}
공격받는 Monster
// 몬스터 기본 클래스 - IDamageable 인터페이스 구현, 추상 클래스
public abstract class Monster : MonoBehaviour, IDamageable
{
public float hp; // 몬스터 체력
// 몬스터마다 체력 설정 방식이 다르므로 추상 메서드로 선언
public abstract void SetHealth();
void Start()
{
// 게임 시작 시 각 몬스터의 체력 설정 호출
SetHealth();
}
// 데미지를 입었을 때 호출되는 함수
public void TakeDamage(float damage)
{
hp -= damage; // 체력 차감
if (hp <= 0f) // 체력이 0 이하가 되면
Death(); // 사망 처리 함수 호출
}
// 몬스터 사망 시 호출되는 함수
public void Death()
{
Debug.Log("몬스터 죽음");
// 여기서 몬스터 사망 효과나 오브젝트 제거 처리 가능
}
}
체력설정_ 추상화와 다형성
public class Orc : Monster
{
public override void SetHealth()
{
hp = 100f;
}
}
public class Goblin : Monster
{
public override void SetHealth()
{
hp = 30f;
}
}
[아이템 획득/사용/버리기 실습]
public class Character : MonoBehaviour
{
// 현재 장착한 아이템을 저장하는 인터페이스 타입 변수
public IDropItem currentItem;
void Update()
{
// 마우스 왼쪽 버튼 클릭 시 현재 아이템 사용
if (Input.GetMouseButtonDown(0))
currentItem.Use();
// B 키를 누르면 현재 아이템 버리기
if (Input.GetKeyDown(KeyCode.B))
currentItem.Drop();
}
private void OnTriggerEnter(Collider other)
{
// 충돌한 대상이 IDropItem 인터페이스를 구현하는지 확인
if (other.GetComponent<IDropItem>() != null)
{
충돌한 대상에서 IDropItem 컴포넌트 가져오기 (인터페이스 타입으로)
IDropItem item = other.GetComponent<IDropItem>();
item.Grab(); // 아이템 획득 처리
currentItem = item; // 현재 아이템으로 설정
}
}
}
Q: IDropItem item = other.GetComponent<IDropItem>(); 에서 왜 인터페이스 타입으로 캐스팅 하나? (이미 인터페이스 타입 같은데)
A: GetComponent<T>()는 해당 컴포넌트가 존재하면 그 컴포넌트의 참조를 반환
그런데 GetComponent<T>() 호출은 비용이 꽤 크기 때문에 한 번 호출해서 반환받은 값을 변수에 저장해두면 이후에 재사용할 때 다시 호출하지 않아도 됨.
오버로딩, 상속, 추상화, 인터페이스를 배우면서 코드 구조를 효율적으로 설계하는 방법을 알게 되었다.
비슷한 기능을 깔끔하게 정리하고, 확장성과 재사용성을 높일 수 있어 실무에서도 꼭 필요한 개념이라는 걸 느꼈다.
앞으로 직접 여러 구조를 만들어 보면서 더 익숙해지고 싶다.
'프로그래밍 > 유니티 부트캠프' 카테고리의 다른 글
| 유니티(상속/인터페이스 연습/layer) _ 멋쟁이사자처럼 유니티 부트캠프 후기 24회차 (0) | 2025.06.18 |
|---|---|
| 유니티(캡슐화,인터페이스/상속 실습 - 몬스터, 아이템) _ 멋쟁이사자처럼 유니티 부트캠프 후기 23회차 (2) | 2025.06.17 |
| 유니티(형변환,객체지향프로그래밍) _ 멋쟁이사자처럼 유니티 부트캠프 후기 21회차 (0) | 2025.06.13 |
| 유니티(게임 다시하기, 빌드하기, RenderTexture 이용해 CCTV, 미니맵 만들기, Lotto 구현) _ 멋쟁이사자처럼 유니티 부트캠프 후기 20회차 (0) | 2025.06.13 |
| 유니티(Video Player 이해, TV와 리모컨 실습, 고양이게임 마무리) _ 멋쟁이사자처럼 유니티 부트캠프 후기 19회차 추가학습 (1) | 2025.06.12 |