using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(Block))]
public class BlockEditor : Editor
{
    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();

        Block block = target as Block;
        if (GUILayout.Button("제거"))
        {
            Debug.Log($"[{block.row},{block.col}]을 제거 합니다.");
        }
    }
}

 

https://docs.unity3d.com/ScriptReference/Editor.OnInspectorGUI.html

 

Unity - Scripting API: Editor.OnInspectorGUI

Success! Thank you for helping us improve the quality of Unity Documentation. Although we cannot accept all submissions, we do read each suggested change from our users and will make updates where applicable. Close

docs.unity3d.com

 

 

  • OnInspectorGUI 메서드는 Unity의 Inspector에서 해당 컴포넌트(Block)의 GUI를 그리는 메서드
  • base.OnInspectorGUI()는 기본적으로 해당 컴포넌트의 Inspector를 그리는 기능을 수행

 

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(Board))]
public class BoardEditor : Editor
{
    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();
        
        Board board = target as Board;

        if (GUILayout.Button("배열 요소 출력"))
        {
            board.PrintBoard();;
        }
    }
}

 

 

public void PrintBoard()
    {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < board.GetLength(0); i++)    //행
        {
            for (int j = 0; j < board.GetLength(1); j++)    //열 
            {
                Block block = board[i, j];
                string strElement = (block == null) ? "null" : block.blockType.ToString();
                sb.Append($"[{i},{j}] = {strElement}  ");
            }
            sb.AppendLine();
        }
        Debug.Log(sb);
    }

 

virtual 키워드는

기본 클래스에서 정의된 메서드를

파생 클래스에서 재정의하도록 허용

 

static, abstract, private 한정자와 함께 사용 불가

 

override 한정자?

상속된 메서드의 구현을 확장하거나 수정

 

https://www.youtube.com/watch?v=kmsocjH-keQ&list=PLTFRwWXfOIYBmr3fK17E0VhKPyYrGy75z&index=39

 

base 키워드?

파생 클래스 내에서 기본 클래스의 맴버에 엑세스하는데 사용

 

부모클래스에서 virtual
파생 클래스에서 override

자식 클래스에서 부모클래스 맴버 엑세스 base

 

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Step37_2
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Marine marine = new Marine();
            marine.name = "마린1";

            Firebat firebat = new Firebat();
            firebat.name = "파이어뱃1";

            marine.Attack();
            firebat.Attack();
        }
    }
}

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Step37_2
{
    class TerranUnit
    {
        public string name;
        //생성자
        public TerranUnit()
        {
            Console.WriteLine("TerranUnit 클래스의 생성자");
        }
        
        public virtual void Attack()
        {
            Console.WriteLine("{0}이(가) 공격 합니다", this.name);
        }
        protected void Reload(string weaponName) //자식만 접근 가능
        {
            Console.WriteLine("{0}이(가) {1}을 장전을 합니다", this.name, weaponName); ;
        }
    }
}

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Step37_2
{
    internal class Marine : TerranUnit
    {
        //생성자
        public Marine()
        {
            Console.WriteLine("Marine클래스의 생성자");
        }
        public override void Attack()
        {
            base.Reload("총");
            Console.WriteLine("{0}이(가) 총으로 공격합니다.", this.name);
        }
    }
}

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace Step37_2
{
    internal class Firebat : TerranUnit
    {
        public Firebat()
        {
            Console.WriteLine("Firebat클래스의 생성자");
        }

        public override void Attack()
        {
            base.Reload("화염방사기");
            Console.WriteLine("{0}이(가) 화염방사기로 공격합니다.", this.name);
        }
        
        
    }
}

'Study > C#' 카테고리의 다른 글

[C#] 업캐스팅, 다운캐스팅  (0) 2024.06.13
[C#] 생성자 연결  (0) 2024.06.12
[C#] 상속  (1) 2024.06.03
[C#] static 한정자  (0) 2024.06.02
[C#] this 키워드  (0) 2024.05.31

virtual?

 

요약하자면,,

부모 클래스에서 virtual 키워드를 사용하여 함수를 만들면, 자식 클래스에서 이 함수를 재정의 할 수 있도록 허용

 

특징 :

 1. virtual 이 붙은 함수는 자식 클래스에서 재정의가 가능하다.

 2. 자식 클래스에서는 new 또는 override 키워드가 사용가능하다.

    - override는 재정의를 하겠다는 확장의 의미이고, new 는 기본 클래스를 숨기는 의미이다. 

 3. 자식클래스의 함수 시그니쳐가 동일해야 재정의가 가능하다.

 4. 자식클래스의 함수는 base 키워드를 사용해 부모 클래스의 함수를 호출 할 수 있다.

 5. abstract 와는 달리 자식클래스에서 구현은 선택이다. (구현 안하면 부모의 함수 사용)

 6. static, abstract, private,sealed 키워드와는 사용이 불가능하다.

 

그럼 왜 사용할까?

public class Monster
{
    public virtual void hit()
    {
        Console.WriteLine("Monster hit");
    }
}
 
public class Orc : Monster
{
    public override void hit()
    {
        Console.WriteLine("Orc hit");
    }
}
 
public class Elf : Monster
{
    public new void hit()
    {
        Console.WriteLine("Elf hit");
    }
}
 
public class Wolf : Monster
{
    public void hit()
    {
        Console.WriteLine("Wolf hit");
    }
}

 

class Program
 {
     static void Main(string[] args)
     {
         Monster monster1 = new Monster();
         Orc monster2 = new Orc();
         Elf monster3 = new Elf();
         Wolf monster4 = new Wolf();
 
         monster1.hit();
         monster2.hit();
         monster3.hit();
         monster4.hit();
 
         Monster monster5 = new Orc();
         Monster monster6 = new Elf();
         Monster monster7 = new Wolf();
 
 
         Console.WriteLine("////////////////////");
         monster5.hit();
         monster6.hit();
         monster7.hit();
 
     }
 }

 

이런식으로 하나씩 입력을 하면 원하는 값은 얻을 수 있지만

나중에 더 많아지면 코드가 길어지면 자연스럽게 코드가 무거워지고 가독성이 떨어지게 된다.

 

virtual 키워드로 지정된 메서드는 가상 메서드가 되는데 가상 메서드는 자식 클래스가 오버라이드 할 수 있도록 허용된다.

자식 클래스는 override 키워드를 사용해 부모 클래스의 가상메서드를 재정의 할 수 있다.

override?

 

기반 클래스에서 선언된 메소드를 자식 클래스에서 재정의

기반 클래스에서 오버라이딩할 메소드를 미리 virtual로 한정

파생 클래스는 virtual 메소드를 override한정자를 이용하여 재선언

 

즉, 가상메서드는 자식 클래스가 오버라이드 할 수 있도록 허용된 메서드

 

base?

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Person : MonoBehaviour
{
   public virtual void Work()
    {
        Debug.Log("일하다");
    }
}

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Salesman : Person {
    public override void Work()
    {
        base.Work();
        Debug.Log("나는 셀러리맨이다");
    }
    private void Start()
    {
        Work();
    }
}

 

보기와 같이 메서드의 이름이 Work로 같이 정의되어도 자식클래서에서 같은 이름 접근가능하고

부모클래스를 호출할 수 있다.

 

혹시나 부모클래스의 메소드가 자식 클래스에 의해 변형이 될가 봐 테스트 해보았고,

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Salesman : Person {
    public override void Work()
    {
        base.Work();
        Debug.Log("나는 셀러리맨이다");
    }
    private void Start()
    {
        Person person = new Person();
        person.Work();
    }
}

 

 

결론은 보기과 같이 "아니" 다.

 

ChatGpt에게 수업이 끝나기 전 간단한 예제를 내달라 했는데 혼자서 입력해봤던 것과 난이도가 같아서

더 어려운 예제를 풀 것이다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Fish : MonoBehaviour
{
    //1.물고기를 나타내는 Fish 클래스를 작성합니다.
    //이 클래스에는 Swim() 메서드가 있어야 합니다. 이 메서드는 "물고기가 헤엄칩니다."라는 메시지를 출력합니다.
    public virtual void Swim()
    {
        Debug.Log("물고기가 헤엄칩니다.");
    }

    private void Start()
    {
        Swim();
    }
}

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Goldfish : Fish
{
    //2.Fish 클래스를 상속받는 Goldfish 클래스를 작성합니다.
    //이 클래스에는 Swim() 메서드를 오버라이드하여 "금붕어가 헤엄칩니다."라는 메시지를 출력하도록 구현합니다.

    public override void Swim()
    {
        Debug.Log("금붕어가 헤엄칩니다.");
    }
}

 

 

자식클래스가 먼저 호출되고 부모클래스가 잇따라 호출되었다.

'낙서장 > C#' 카테고리의 다른 글

[C#] 메서드 오버로딩  (0) 2024.06.02
상속과 다형성  (1) 2024.03.08
흐름 제어  (1) 2024.02.26
데이터를 가공하는 연산자  (0) 2024.02.25
데이터를 담는 변수와 상수  (0) 2024.02.22

+ Recent posts