🔥 메서드 오버로딩과 오버라이딩의 용어가 헷갈려서 작성하는 포스트 🔥


메서드 오버로딩  (overloading)

같은 이름의 메서드를 중복하여 정의하는 것
: 매개변수의 개수나 타입이 달라야 함
: 객체 지향 프로그래밍의 특징 중 하나인 "다형성"의 특징

public class Monster
{
    protected int hp;
    protected string name;
    protected float damage;

    public void SettingMonster() 
    {
            
    }
    public void SettingMonster(int hp)
    {

    }
    public void SettingMonster(int hp , string name)
    {

    }
    public void SettingMonster(int hp, string name , float damage)
    {

    }
}

: 함수이름은 "SettingMonster"로 같다

1. 첫 번째 메서드는 매개변수가 없다.

2. 두 번째 메서드는 int를 매개변수로 가진다.

3. 세 번째 메서드는 int, string을 매개변수로 가진다

4. 네 번째 메서드는 int, string, float를 매개변수로 가진다.

=> 메서드 오버로딩

 

- 생성자 오버로딩

public class Monster
{
    protected int hp;
    protected string name;
    protected float damage;

    public Monster() 
    {
    
    }
    public Monster(int hp)
    {

    }
    public Monster(int hp , string name)
    {

    }
    public Monster(int hp, string name , float damage)
    {

    }
}

: 생성자 또한 오버로딩 할 수 있다. 

 

- 생성자 오버로딩 사용 

    public Monster()
    {
        Console.WriteLine("매개변수가 없는 생성자입니다.");
    }
    public Monster(int hp)
    {
        this.hp = hp;
        Console.WriteLine($"하나의 매개변수를 가지는 생성자 입니다 {this.hp}");
    }
    public Monster(int hp, string name)
    {
        this.hp = hp;
        this.name = name;
        Console.WriteLine($"두개의 매개변수를 가지는 생성자 입니다 {this.hp} / {this.name}");
    }
    public Monster(int hp, string name, float damage)
    {
        this.hp = hp;
        this.name = name;
        this.damage = damage;
        Console.WriteLine($"세개의 매개변수를 가지는 생성자 입니다 {this.hp} / {this.name} / {this.damage}");
    }

: 출력 시 해당 메서드가 실행되었는지 확인하기 위해서 출력문을 작성하였다.

 

- 실행

        static void Main(string[] args)
        {
            // 1. 매개변수가 없는 생성자 
            Monster monster = new Monster();

            // 2. 매개변수가 한개인 생성자
            Monster monster2 = new Monster(10);

            // 3. 매개변수가 두개인 생성자
            Monster monster3 = new Monster(10 , "SLIME");

            // 4. 매개변수가 세개인 생성자
            Monster monster4 = new Monster(10 , "SLIME" , 20f);
        }

: 입력된 매개변수와 유형에 따라 적절한 생성자가 매칭된다.

 

- 출력

 

- 그래서 오버로딩을 왜 사용할까?

1. 메서드에 사용되는 이름을 절약할 수 있다. 
2. 같은 기능을 하는 메서드를 하나의 이름으로 정의할 수 있다.

 

- 만약 오버로딩을 사용하지 않고 SettingMonster() 메서드를 사용해 보겠다.

        public class Monster
        {
            protected int hp;
            protected string name;
            protected float damage;

            public void SettingMonster_NoneParemeter()
            {

            }
            public void SettingMonster_OneParemeter(int hp)
            {
               
            }
            public void SettingMonster_TwoParemeter(int hp, string name)
            {

            }
            public void SettingMonster_TreeParemeter(int hp, string name, float damage)
            {
              
            }
        }

: 파라미터가 없는 메서드, 한 개만 있는 메서드, 두 개 있는 메서드, 세 개 있는 메서드 이름을 다 다르게 해야 한다.

: 해당 메서드는 Monster의 필드를 세팅해 주는 같은 역할을 하는데, 이름이 다 다르다. 

-> 사용할 때 불편하다! 


메서드 오버라이딩  (overriding)

: 상속받은 부모 클래스의 메서드를 '자식클래스'에서 재정의 하여 사용하는 것
: 자식클래스에서 오버라이딩할 메서드와 이름, 매개변수의 개수와 타입, 반환값이 같아야 함

 

- 함수이름만 같다면? 

public class Monster
{
    protected int hp;
    protected string name;
    protected float damage;

    public void Attack() 
    {
        Console.WriteLine("Monster의 Attack");
    }

}

public class Orc : Monster 
{
    public void Attack() 
    {
        Console.WriteLine("Orc의 Attack");
    }
}

static void Main(string[] args)
{
    Orc orc = new Orc();
    orc.Attack();
}

: 부모 메서드와 이름이 같은 메서드를 작성했을 때

 

-출력

: Orc클래스의 Attack() 메서드에 커서를 가져다 대면

: " 상속된 Attack() 메서드를 숨깁니다 "라는 경고문구가 뜬다. 

: new 키워드를 사용하라고 한다.

        public class Orc : Monster 
        {
            public new void Attack() 
            {
                Console.WriteLine("Orc의 Attack");
            }
        }

: new 키워드를 사용함으로써, 상위 메서드와는 다른 새로운 메서드를 정의한다고 할 수 있다.

 

- virtual , override 키워드 사용하기 

public class Monster
{
    protected int hp;
    protected string name;
    protected float damage;

    public virtual void Attack() 
    {
        Console.WriteLine("Monster의 Attack");
    }
}

public class Orc : Monster 
{
    public override void Attack() 
    {
        Console.WriteLine("Orc의 Attack");
    }
}

static void Main(string[] args)
{
    Orc orc = new Orc();
    orc.Attack();

}

: 부모클래스에서 virtual, 자식클래스에서 override 키워드를 사용함으로써 "오버라이딩"을 명시적으로 표현한다.

 

- return 타입이 같아야 한다

: 오버라이딩 하는 메서드의 반환타입이 같아야 한다. 

: 상위 Attack()은 void일 때 오버라이딩 한 메서드의 return 타입을 바꾸게 되면 오류가 난다. 

 

- base 키워드

        public class Orc : Monster 
        {
            public void Attack() 
            {
                base.Attack();
                Console.WriteLine("Orc의 Attack");
            }

        }

: base 키워드를 사용하게 되면 부모의 Attack() 메서드도 실행한다.

 

-출력

 


오버로딩한 메서드를 오버라이딩

: 코드를 작성하다 보면 오버로딩과 오버라이딩을 같이 사용하는 경우가 많은 것 같다.

 

- Monster 클래스

public class Monster
{
    protected int hp;
    protected string name;
    protected float damage;

    public virtual void Attack() 
    {
        
    }
    public virtual void Attack(float stage) 
    { 
    
    }
    public virtual void Attack(float stage, float critical) 
    {
    
    }
}

: 메서드 오버로딩을 사용하여 같은 이름의 메서드를 3개 정의했다. 

 

- Orc 클래스

 public class Orc : Monster 
 {
     public Orc(int h , string n, float d) 
     {
         this.hp = h;
         this.name = n;
         this.damage = d;
     }

     public override void Attack()
     {
         Console.WriteLine($"오크의 기본 공격: {damage * 1.5f} 데미지");
     }

     public override void Attack(float stage)
     {
         Console.WriteLine($"오크의 스테이지 {stage} 기반 공격: {damage * stage * 1.5f} 데미지");
     }

     public override void Attack(float stage, float critical)
     {
         Console.WriteLine($"오크의 크리티컬 공격: {damage * stage * critical * 1.5f} 데미지");
     }
 }

: 메서드 오버라이딩을 통해서 하위 Orc 클래스에서 재정의했다.

: 오버로딩한 Attack() 메서드를 오버라이딩 했다! 

 

- Main

        static void Main(string[] args)
        {
            Orc orc = new Orc(100, "오크", 10f);

            orc.Attack();                   // 기본 공격
            orc.Attack(2.0f);               // 스테이지 기반 공격
            orc.Attack(2.0f, 1.5f);         // 크리티컬 공격
        }

 

- 출력

 


<마치며>

가상함수에 대해 찾아보던 중, 정적바인딩과 동적바인딩에 관해서 알게 되었다. 
추후 공부 후 정적/동적바인딩에 대해서도 블로그글을 작성하고 싶다. 


<도움이 되었던 링크>

https://www.tcpschool.com/java/java_usingMethod_overloading

 

코딩교육 티씨피스쿨

4차산업혁명, 코딩교육, 소프트웨어교육, 코딩기초, SW코딩, 기초코딩부터 자바 파이썬 등

tcpschool.com

https://www.tcpschool.com/java/java_inheritance_overriding

 

코딩교육 티씨피스쿨

4차산업혁명, 코딩교육, 소프트웨어교육, 코딩기초, SW코딩, 기초코딩부터 자바 파이썬 등

tcpschool.com

 

+ Recent posts