virtual, abstract, interface 개념 (+ override와 overload)
2024. 4. 9.
override / overload

 

오버라이딩 - 부모에서 정의된 멤버 메서드를 자식에서 재정의하는 것

오버로딩 - 이름은 같은데 ,매개변수 (parameter)가 다른 메서드를 만드는 것

Virtual

-재정의(override)가 가능하다.

=> 가능한것이지 반드시 해야된다는 것은 아니다. 그 자체로 완전하기 때문이다.

 

Abstract

 - 추상 클래스 선언 및 메서드에서 사용됨

 - 파생 클래스에 공통적인 정의를 제공 / 각각의 파생 클래스에서 사용될 기능을 강제적으로 재정의

    => 파생 클래스는 추상클래스를 상속 받은 자식 클래스를 의미한다.

    => abstract 키워드가 붙으면 그 자체로는 불완전하여 파생 클래스에서 "반드시" 재정의 해야한다.

    => abstract 키워드는 인스턴스화할 수 없다.

      +) 인스턴스는 어떤 클래스에 속하는 객체를 의미하므로 인스턴스화란 클래스로부터 객체를 만드는 과정을 의미한다.   - abstract 메서드에 virtual 키워드를 사용할 수 없다.

abstract 메서드에 virtual 키워드 사용불가

 

-Abstract 키워드를 사용하는 예시를 보기위해 하단의 코드를 참고하자. 먼저 상속에 관해 이해해야한다.

   

using System;

public abstract class Unit
{
    public string name;

    public Unit(string name)
    {
        this.name = name;
        Console.WriteLine("Unit 클래스의 생성자");
    }

    public abstract void Move();
}

=> Unit 클래스에서 Move() 메서드 앞에 abstract 키워드를 사용하고 있다. 이를 기억해두자.

using System;

public class Marine : Unit
{
    public Marine(string name): base(name)
    {
        Console.WriteLine("{0}이(가) 생성되었습니다.", this.name);
    }

    public override void Move()
    {
        Console.WriteLine("{0}이(가) 이동합니다.", this.name);
    }
}

-abstract 키워드를 사용하여 부모 클래스에서 정의된 Move() 메서드는 파생(자식) 클래스에서 반드시 재정의되어야 한다.

=> override 를 사용하여 Move()메서드를 재정의하고 있음을 확인할 수 있다.

using System;

class Program
{
    static void Main(string[] args)
    {
        Marine marine = new Marine("마린1");
        marine.Move();
    }
}

실행 결과

- marine 변수를 선언하고, 인스턴스화하고 있다.

- 이 marine 변수를 사용하여 Marine 클래스의 멤버인 Move 메서드에 접근한다.

더보기

- 실행 결과를 살펴보면 Main에서 Marine타입의 marine변수에 new 키워드를 사용하여 인스턴스화하므로 Marine 클래스의 인스턴스가 생성되고, 생성자가 호출된다.

- Marine 클래스의 생성자는 base 키워드를 사용한다.

  => 부모 클래스인 Unit 클래스의 멤버에 접근할 수 있게 한다.

 => 부모 클래스의 오버로딩된 생성자 메서드를 자식에게서 구현하고자할 때 사용한다.

 => 따라서 Marine 클래스의 인스턴스가 생성되면서 base 키워드에 의해 부모의 생성자 메서드가 호출된 후, 재정의 된  Console.Writeline("{0}이(가) 생성되었습니다.", this.name);부분이 실행된다.

즉, Marine클래스의 인스턴스가 생성될 때, Unit클래스의 생성자 메서드가 호출된 후 재정의된 부분에 추가된 부분이 실행된다고 보자.

- 따라서,  "Unit 클래스의 생성자" 부분이 먼저 출력된 후, 마린1이(가) 생성되었습니다. 와같은 결과가 출력된 것이다.

 

 

 

 

Interface

- 구현되어 있지 않은 메서드들의 정의만을 포함한다.

=> 구현부가 없다. 메서드, 이벤트, 인덱서, 프로퍼티 만을 가질 수 있다. (필드 포함 불가)

                                => 추상화를 달성하고, 객체가 서로 상호작용할 수 있도록 하는 도구이다.

- 인스턴스화 될 수 없다. 인스턴스를 만들 수 없지만, 인터페이스를 상속받는 클래스의 인스턴스를 만들 수 있다.

- 클래스에서 상속받아 구현할 수 있다.

=> 즉, 몸체없는 메서드를 만들고 클래스를 상속받아 사용하는 등의 면을 보면 추상클래스와 유사하다 볼 수 있다.

- 그러나, 추상 클래스와 달리 다중 상속이 가능하다. => 클래스는 인터페이스를 여러 개 상속 받는 것이 가능하다.

 

- 인터페이스는 자신을 상속받는 클래스에게 오버라이딩을 강제한다.

- 접근 제한 한정자를 사용할 수 없고, 모든 것이 public으로 선언된다.

=> 인터페이스에는 선언된 메서드 제한자가 존재하지 않아도, public 추상 메서드라고 생각하자.

 

+) 인터페이스 선언시 I를 붙여주는 것이 관례이다.

 

- 자기 자신을 인스턴스로 삼을 수 없다.

interface는 자기 자신을 인스턴스로 사용 불가

interface IZerg
{
    void Transformation();
    void Burrow();
}

interface IRecoveryHp
{
    void RecoverHp();
}
using System;

public class Hydralisk : IZerg, IRecoveryHp
{
    public Hydralisk()
    {

    }

    public void Burrow()
    {
        //땅속에 숨기
    }

    public void Transformation()
    {
        //변환 
    }

    public void RecoverHp()
    {
        //체력 회복 
    }
}

 

 

참고내용)

 

https://jettstream.tistory.com/160

https://smilejsu.tistory.com/2123

 

myoskin