Unity 기본13 - 오버로드(overload), 오버라이드(override), 추상(abstract), 인터페이스(interface)
1. 오버로드(overload)
하나의 이름에 여러개의 기능을 싣다
함수 이름이 같은데 다른 기능을 하도록 만들다
대신 함수들의 parameter가 서로 다르다
parameter의 개수가 다르거나, 자료형 타입이 다르면 함수 이름이 같아도 다른 함수가 된다
2개의 Dump method를 가지는 Box라는 class 생성
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Box
{
public void Dump(string thing)
{
Debug.Log(thing + " 버리겠습니다.");
}
public void Dump(string who, string thing)
{
Debug.Log(who + "씨 " + thing + " 좀 버려줘요.");
}
}
Box class를 하나 만들고, Dump method에 "휴지" 하나만 준다면?
인자 하나만 받는 첫번째 method가 알아서 불러짐
Dump에 2개의 인자를 준다면?
알아서 2번째 인자 2개를 가지는 method를 불러온다
함수가 같은 이름이어도, parameter가 다르면 따로 구현이 가능하다
인자의 타입이 달라도 마찬가지다.
public void Dump(int number)
{
Debug.Log(number + "개 버렸습니다.");
}
완전히 서로 다른 기능인데, 오버로드를 해버리면 코드가 읽기 힘들어진다.
비슷하지만 약간 다른 기능의 경우에 사용하는 것을 권장
완전 같은 기능인데 다른 식으로 호출하고 싶은 경우,
2. 오버라이드(override)
상속받은 자식 클래스의 method가 부모 클래스의 method를 덮어 써서 대체하다
TrashBin이라는 class를 만들고, 이전에 만든 Box를 상속시킨다
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TrashBin : Box
{
}
Box에 introduce라는 method를 생성
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Box
{
public void introduce()
{
Debug.Log("안녕하세요. 박스입니다.");
}
public void Dump(string thing)
{
Debug.Log(thing + " 버리겠습니다.");
}
public void Dump(string who, string thing)
{
Debug.Log(who + "씨 " + thing + " 좀 버려줘요.");
}
public void Dump(int number)
{
Debug.Log(number + "개 버렸습니다.");
}
}
오버라이드될 가능성이 있는 부모 클래스의 method에는 virtual 선언을 한다
public virtual void introduct() 이렇게
자식 클래스에서 실제로 override할 때는... override 선언을 한다
public override void introduct() { base.introduce() };
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TrashBin : Box
{
public override void introduce()
{
base.introduce();
}
}
여기서 base.introduce();는 부모의 introduce를 호출한다는 의미다.
얘를 지우고 자식에서 새롭게 만들 기능을 작성
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TrashBin : Box
{
public override void introduce()
{
Debug.Log("안녕하세요. 전 쓰레기통입니다.");
}
}
TrashBin이라는 class를 만들고 introduce()를 하면 "안녕하세요. 전 쓰레기통입니다"라고 나온다
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HelloWorld : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
Box aBox = new Box();
aBox.introduce();
TrashBin trashbin = new TrashBin();
trashbin.introduce();
}
// Update is called once per frame
void Update()
{
}
}
base.introduce();를 남겨두면, 자식 클래스의 introduce()에서 부모 클래스의 introduce()도 쓰게된다
3. 추상(abstract)
이름만 있고 구현되지 않은 method
부모 클래스가 추상 method를 만들어놓으면, 자식 클래스에서 그 기능을 구현하는 것
추상 method가 있는 class를 추상 class라고 부른다
기능이 없기 때문에 그대로 사용하지는 못함
추상 method를 구현할 자식이 있어야하고, 그 자식의 이름으로 instance를 만들어야함
바로 사용할 수도 없는 추상 method는 왜 쓰는건가? 가독성이 좋아짐?
Animal이라는 class 생성
추상 method를 만들기 위해 public abstract void Fly()라고 abstract를 선언
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Animal
{
public abstract void Fly()
{
}
}
에러가 나는데 2가지 이유가 있다고함
추상 method는 기능이 없어야하므로 {}을 선언할 수 없다
abstract method가 있는 class는 abstract class로 선언해야함
추상 class지만 구현이 된 method가 존재해도 된다
하나라도 추상 method가 존재한다면 추상 class가 된다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public abstract class Animal
{
public abstract void Fly();
public void introduce()
{
Debug.Log("안녕하세요 동물입니다.");
}
}
추상 class를 생성해서 쓸려고 new Animal();하면 에러가 남
기능이 구현되지 않은 추상 method가 있기 때문에 그대로 사용할 수가 없다
상속을 받아서 구현해줘야만 쓸 수 있다
Animal class를 상속받는 Bird를 만든다
추상 method를 구현하지 않았다고 일단 에러가 남
Bird가 추상 class가 안되려면, 상속받은 추상 method Fly()를 구현해줘야한다
부모의 Fly()를 받아 구현하므로 override가 된다
Animal의 일종인 새와 곤충에 대해 둘은 날다라는 기능이 다르기 때문에,
날기 위해 해야할 일이 새와 곤충이 다르기 때문에, 일단 부모인 Animal에는 기능을 구현해놓지 않고
상속받은 자식 새와 곤충에게 각각 구현하라고 남겨놓는것
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Bird : Animal
{
public override void Fly()
{
Debug.Log("퍼덕퍼덕");
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Bug : Animal
{
public override void Fly()
{
Debug.Log("위잉위잉");
}
}
추상 method Fly()를 Bird, Bug에서 구현했기 때문에 Bird, Bug는 추상 class가 아니다.
new Animal()은 못하지만, 이제 new Bug(), new Bird()는 만들어서 쓸 수 있다
Animal class를 쓰고 싶다면,
Animal some = new Bug(); 이런식으로 쓸 수 있긴 있다
그리고 some.Fly();를 한다면?
some에 Bug()가 들어가있다면 Bug()의 Fly()가, Bird()가 있다면 Bird()의 Fly()가 실행
이것을 다형성( polymorphism )이라고 부른다.
하나의 객체가 여러 타입을 가질 수 있는 것으로, 부모 타입의 객체에 자식 타입의 instance를 대입하는 것이다.
추상 class의 특징은 여러 자식들의 하나의 조상이 되며,
이 추상 class의 어떤 기능을 바꾸면, 상속받은 모든 자손들도 전부 한번에 바뀐다
4. 인터페이스(interface)
어떤 이름의 메소드가 여기 존재하기로 했다는 약속
class와 비슷한 형태로 문서화
public interface ITurnOnable로 class 말고 interface라고 선언
class 대신 하나의 약속을 만드는 것
class와 구분하기 위해 이름 앞에 대문자 I를 붙이는 관습이 있다
원래 이름이 TUrnOnable인데 인터페이스라서 I가 앞에 붙어있음
2개의 method TurnOn, TurnOff를 생성
추상 method처럼 기능이 없고 이름만 써져있다
근데 abstract 선언을 안함
interface는 method들의 이름으로만 구성됨
interface의 모든 method들은 추상 method처럼 이름만 있다
다른 class에서 이 method들을 구현해야한다?
Car, TV라는 class를 생성하고 ITurnOnable이라는 인터페이스를 상속받도록
두 클래스가 모두 ITurnOnable이라는 인터페이스 규약을 따르도록 함
부모 클래스를 상속받듯이, 뒤에 인터페이스 이름을 썼지만, 인터페이스를 상속받는다는 뜻은,
이 TV class가 이 인터페이스 ITurnOnable를 구현하겠다는 뜻
인터페이스를 구현한다는 뜻은 TV class내에 인터페이스 ITurnOnable의 method들이 실제 기능을 가지는 것
그래서 구현하지 않으면 이렇게 빨간줄이 그어져있다
인터페이스가 class 뒤에 써 있으면, 해당 클래스 내에는 인터페이스 내의 method들이 있을 것이라고 알 수 있다
인터페이스도 타입명으로 사용할 수 있고, 해당 인터페이스에 Car이나 TV instance를 넣을 수 있음
당연히 ITurnOnable som = new ITurnOnable();이라고는 사용 불가능함. 추상 method가 있기 때문
5. 다중상속
class의 상속도 받고, interface 규약도 따르는 class를 만들고 싶다면?
둘다 쉼표로 연결해서 Car : Animal, ITurnOnable같이 쓰면 된다.
추상 class를 상속받으면 추상 method를 구현해야하는데 override를 해야하고,
interface를 받으면, interface의 method를 구현해야하는데 이건 부모 class가 아니니까 override는 아니네?
일종의 다중상속이긴 하지만, C#은 부모 base class를 여러개 가지는 것을 허용하지 않는다
부모 class는 하나여야하지만, interface를 여러개 상속받을 수 있다
'프로그래밍 > Unity&C#' 카테고리의 다른 글
Unity 게임 카메라 움직이는 코드 분석 (0) | 2024.05.04 |
---|---|
사람의 방향키 입력을 받아 공을 굴리는 C# 프로그램 분석 (0) | 2024.05.02 |
unity 기본12 - scope, 캡슐화, getter, setter, public, private, protected (0) | 2024.04.26 |
Unity 기본11 - class 상속, is, as 연산자 (0) | 2024.04.25 |
Unity 기본10 - class 만들기 (0) | 2024.04.24 |