c# virtual 키워드




추상 함수와 가상 함수의 차이점은 무엇입니까? (16)

추상 함수와 가상 함수의 차이점은 무엇입니까? 어떤 경우 가상 또는 추상을 사용하는 것이 좋습니다? 더 정확한 접근법은 무엇입니까?


  1. abstract 클래스 만 abstract 멤버를 가질 수 있습니다.
  2. abstract 클래스에서 상속 한 비 abstract 클래스는 abstract 멤버를 override 해야합니다 .
  3. abstract 멤버는 암시 적으로 virtual 입니다.
  4. abstract 멤버는 구현을 제공 할 수 없습니다 (일부 언어에서는 abstract pure virtual 이라고 함).

C #에서는 가상 클래스를 호출하지 않습니다.

함수의 경우

  1. 추상 함수는 서명 만 갖고 드라이브 클래스는 기능으로 대체해야합니다.
  2. 가상 함수는 드라이브 클래스가 요구 사항에 따라 기능을 대체 할 수도 있고 그렇지 않을 수도있는 기능의 일부를 보유합니다.

요구 사항을 결정할 수 있습니다.


가상 메서드는 기본적으로 상속자가 원하는대로 기능을 확장 할 때 사용합니다.

상속자가 기능을 구현하기를 원할 때 추상 메소드를 사용합니다 (이 경우에는 선택 사항이 없습니다)


나는 다음과 같은 클래스들에 대한 몇 가지 개선 사항들을 (다른 답변들로부터) 간단하게 만들었다.

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

namespace TestOO
{
    class Program
    {
        static void Main(string[] args)
        {
            BaseClass _base = new BaseClass();
            Console.WriteLine("Calling virtual method directly");
            _base.SayHello();
            Console.WriteLine("Calling single method directly");
            _base.SayGoodbye();

            DerivedClass _derived = new DerivedClass();
            Console.WriteLine("Calling new method from derived class");
            _derived.SayHello();
            Console.WriteLine("Calling overrided method from derived class");
            _derived.SayGoodbye();

            DerivedClass2 _derived2 = new DerivedClass2();
            Console.WriteLine("Calling new method from derived2 class");
            _derived2.SayHello();
            Console.WriteLine("Calling overrided method from derived2 class");
            _derived2.SayGoodbye();
            Console.ReadLine();
        }
    }


    public class BaseClass
    {
        public void SayHello()
        {
            Console.WriteLine("Hello\n");
        }
        public virtual void SayGoodbye()
        {
            Console.WriteLine("Goodbye\n");
        }

        public void HelloGoodbye()
        {
            this.SayHello();
            this.SayGoodbye();
        }
    }


    public abstract class AbstractClass
    {
        public void SayHello()
        {
            Console.WriteLine("Hello\n");
        }


        //public virtual void SayGoodbye()
        //{
        //    Console.WriteLine("Goodbye\n");
        //}
        public abstract void SayGoodbye();
    }


    public class DerivedClass : BaseClass
    {
        public new void SayHello()
        {
            Console.WriteLine("Hi There");
        }

        public override void SayGoodbye()
        {
            Console.WriteLine("See you later");
        }
    }

    public class DerivedClass2 : AbstractClass
    {
        public new void SayHello()
        {
            Console.WriteLine("Hi There");
        }
        // We should use the override keyword with abstract types
        //public new void SayGoodbye()
        //{
        //    Console.WriteLine("See you later2");
        //}
        public override void SayGoodbye()
        {
            Console.WriteLine("See you later");
        }
    }
}

내 이해하려면 :

추상 방법 :

추상 클래스 만 추상 메소드를 보유 할 수 있습니다. 또한 파생 클래스는 메서드를 구현해야하며 구현이 클래스에 제공되지 않습니다.

가상 메소드 :

클래스는 이것들을 선언 할 수있어 같은 것을 구현할 수 있습니다. 또한 파생 클래스는 메서드를 구현하여이를 재정의해야합니다.


대답은 여러 번 제공되었지만 각각을 사용할시기에 대한 질문은 디자인 타임 결정입니다. 공통 메서드 정의를 고유 한 인터페이스에 묶어 적절한 추상화 수준에서 클래스로 가져 오는 것이 좋습니다. 추상 및 가상 메소드 정의의 공통 집합을 클래스로 덤프하면 일련의 간결한 인터페이스를 구현하는 비 추상적 클래스를 정의하는 것이 가장 좋을 때 클래스를 일관성있게 렌더링 할 수 있습니다. 언제나 그렇듯이 애플리케이션 별 요구 사항에 가장 적합한 것이 무엇인지에 달려 있습니다.


요약 기능 :

  1. 추상 클래스 내에서만 선언 할 수 있습니다.
  2. 여기에는 추상 클래스의 구현이 아닌 메소드 선언 만 포함됩니다.
  3. 파생 클래스에서 재정의해야합니다.

가상 기능 :

  1. 추상 클래스뿐만 아니라 추상 클래스 내에서 선언 될 수 있습니다.
  2. 메소드 구현을 포함합니다.
  3. 재정의 될 수 있습니다.

위 예제의 대부분은 코드를 사용하며 매우 훌륭합니다. 나는 그들이 말하는 것을 더할 필요가 없지만, 다음은 코드 / 기술 용어보다는 유추를 사용하는 간단한 설명이다.

간단한 설명 - 유추 사용 설명

추상 방법

George W Bush를 생각해보십시오. 그는 병사들에게 "이라크에서 싸우라."라고 말한다. 그리고 그게 다야. 그가 지정한 것은 싸움을해야한다는 것입니다. 그는 그 일이 정확히 어떻게 될지는 구체적으로 밝히지 않았다. 하지만 내 말은, 당신은 그냥 나가서 싸울 수 없다는 것입니다. 그게 정확히 무슨 뜻입니까? B-52 또는 내 derringer와 싸워야합니까? 그 구체적인 세부 사항은 다른 사람에게 맡겨져 있습니다. 이것은 추상적 인 방법입니다.

가상 메소드

David Petraeus는 군대에서 최고입니다. 그는 싸움의 의미를 정의했습니다 :

  1. 적을 찾는다.
  2. 그를 중립 시키십시오.
  3. 나중에 맥주를 마시라.

문제는 이것이 매우 일반적인 방법이라는 것입니다. 효과가있는 좋은 방법이지만 때로는 구체적이지 않습니다. Petraeus에게 좋은 점은 그의 주문에 여유와 범위가 있다는 것입니다. 그는 특정 요구 사항에 따라 다른 사람들이 "싸움"에 대한 자신의 정의를 바꿀 수있게했습니다.

개인 작업 Bloggs는 Petraeus의 명령을 읽고 자신의 특정 요구 사항에 따라 자신의 전투 버전을 구현할 수있는 권한을 부여받습니다.

  1. 적을 찾으십시오.
  2. 그를 머리에 쏴.
  3. 집에가
  4. 맥주를 마셔 라.

Nouri al Maliki는 Petraeus에서도 같은 명령을받습니다. 그는 또한 싸울 것입니다. 그러나 그는 보병이 아닌 정치가입니다. 분명히 그는 정치인을 머리에 총격 당할 수는 없다. Petraeus가 가상 메소드를 제공했기 때문에 Maliki는 자신의 특정 상황에 따라 자신의 전투 메소드 버전을 구현할 수 있습니다.

  1. 적을 찾으십시오.
  2. 일부 BS가 혐의를 받고 체포되자.
  3. 집에가
  4. 맥주를 마셔 라.

다시 말해, 가상의 방법은 상용구 지침을 제공합니다. 그러나 이것은 일반적인 지시 사항이며, 특별한 상황에 따라 군대 계층에 속한 사람들이보다 구체적으로 지정할 수 있습니다.

두 사람의 차이점

  • George Bush는 구현 세부 사항을 증명하지 않습니다. 이것은 다른 사람이 제공해야합니다. 이것은 추상적 인 방법입니다.

  • 반면에 Petraeus는 구현 세부 사항을 제공하지만 부하가 더 나은 것을 내놓을 수 있다면 자신의 명령으로 자신의 명령을 무시하는 것을 허락합니다.

도움이되는 희망.


추상 메서드는 구체적인 클래스를 만들기 위해 구현해야하는 메서드입니다. 선언은 추상 클래스에 있고 (추상 메서드가있는 클래스는 추상 클래스 여야 함) 구체적인 클래스로 구현해야합니다.

가상 메서드는 상속을 사용하여 파생 클래스에서 재정의되어 수퍼 클래스의 비헤이비어를 대체 할 수있는 메서드입니다. 재정의하지 않으면 원래 동작을 얻습니다. 그렇게한다면 항상 새로운 행동을 취하게됩니다. 이것은 가상 메소드가 아니라 오버라이드 할 수는 없지만 원래 메소드를 숨길 수 있습니다. 이 작업은 new 수정자를 사용하여 수행됩니다.

다음 예제를 참조하십시오.

public class BaseClass
{
    public void SayHello()
    {
        Console.WriteLine("Hello");
    }


    public virtual void SayGoodbye()
    {
        Console.WriteLine("Goodbye");
    }

    public void HelloGoodbye()
    {
        this.SayHello();
        this.SayGoodbye();
    }
}


public class DerivedClass : BaseClass
{
    public new void SayHello()
    {
        Console.WriteLine("Hi There");
    }


    public override void SayGoodbye()
    {
        Console.WriteLine("See you later");
    }
}

DerivedClass 인스턴스화하고 SayHello 또는 SayGoodbye 호출하면 "안녕하세요"와 "나중에 보자"가 나타납니다. HelloGoodbye 호출하면 "Hello"와 "나중에 보자."가 표시됩니다. 이는 SayGoodbye 가 가상이며 파생 클래스로 대체 될 수 있기 때문입니다. SayHello 는 숨겨져 있기 때문에 기본 클래스에서 호출하면 원본 메서드가 생성됩니다.

추상 메소드는 암시 적으로 가상입니다. 그것들은 존재해야만하는 행동을 정의합니다.


추상 메소드 : 클래스가 추상 메소드를 포함 할 때, 그 클래스는 추상으로 선언되어야한다. abstract 메소드에는 구현이 없으므로,이 추상 클래스에서 파생 된 클래스는이 추상 메소드에 대한 구현을 제공해야합니다.

가상 메소드 : 클래스는 가상 메소드를 가질 수 있습니다. 가상 메소드에는 구현이 있습니다. 가상 메서드가있는 클래스를 상속하면 가상 메서드 재정의하고 추가 논리를 제공하거나 논리를 자신의 구현으로 바꿀 수 있습니다.

사용시기 : 경우에 따라 특정 유형에 특정 메소드가 있어야하지만이 메소드가 어떤 구현을 가져야하는지 모를 수 있습니다.
이 경우이 서명이있는 메소드가 포함 된 인터페이스를 작성할 수 있습니다. 그러나 그러한 경우가 있지만 해당 인터페이스의 구현 자에게 이미 구현을 제공 할 수있는 또 다른 공통 메소드가 있다는 것을 알고 있다면 추상 클래스를 만들 수 있습니다. 그런 다음이 추상 클래스에는 추상 메서드 (재정의해야 함)와 '공통'논리가 포함 된 다른 메서드가 들어 있습니다.

직접 사용할 수 있지만 상속자가 특정 동작을 변경할 수 있도록하려면 반드시 필수는 아니지만 클래스를 사용하는 경우 가상 메서드를 사용해야합니다.


추상 함수 (메소드) :

● 추상 메소드는 abstract 키워드로 선언 된 메소드입니다.

● 몸이 없습니다.

● 파생 클래스에 의해 구현되어야합니다.

● 메소드가 추상적 인 경우 클래스는 추상화되어야합니다.

가상 함수 (메서드) :

● 가상 메소드는 키워드 virtual을 사용하여 선언 된 메소드이며 override 키워드를 사용하여 파생 클래스 메소드에 의해 재정의 될 수 있습니다.

● 재정의 할 것인지 아닌지는 파생 클래스에 달려 있습니다.


추상 함수는 구현이 없으며 추상 클래스에서만 선언 될 수 있습니다. 이렇게하면 파생 클래스가 구현을 제공합니다. 가상 함수는 기본 구현을 제공하며 추상 클래스 또는 비 추상 클래스에 존재할 수 있습니다. 그래서 예를 들면 :

public abstract class myBase
{
    //If you derive from this class you must implement this method. notice we have no method body here either
    public abstract void YouMustImplement();

    //If you derive from this class you can change the behavior but are not required to
    public virtual void YouCanOverride()
    { 
    }
}

public class MyBase
{
   //This will not compile because you cannot have an abstract method in a non-abstract class
    public abstract void YouMustImplement();
}

추상적 인 방법은 항상 가상입니다. 그들은 구현할 수 없습니다.

그것이 가장 큰 차이점입니다.

기본적으로 가상 메소드를 사용하려면 '기본'구현이 있고 하위 클래스가 동작을 변경할 수 있어야합니다.

추상 메소드를 사용하면 자손이 구현을 제공하도록 할 수 있습니다.


항상 추상 함수를 재정의해야합니다.

그러므로:

  • 추상 함수 - 상속자가 자체 구현을 제공해야하는 경우
  • 가상 - 결정할 상속인까지 일 때

바인딩 은 이름을 코드 단위로 매핑하는 프로세스입니다.

후기 바인딩 은 이름을 사용하지만 매핑을 연기한다는 것을 의미합니다. 즉, 먼저 이름을 작성 / 언급하고 후속 프로세스에서 해당 이름에 대한 코드 매핑을 처리하도록합니다.

이제 고려해보십시오.

  • 인간과 비교할 때, 기계는 검색과 분류에 정말 능숙합니다.
  • 기계와 비교할 때, 인간은 발명과 혁신에 정말로 뛰어납니다.

따라서 짧은 대답은 다음과 같습니다. virtual 은 기계 (런타임)에 대한 후기 바인딩 명령입니다. 반면 abstract 은 휴먼 (프로그래머)에 대한 런타임 바인딩 명령입니다.

즉, virtual 이란 다음을 의미합니다.

" 런타임 에 최선을 다해 적절한 코드를이 이름에 바인딩하십시오 : 검색 "

반면 abstract 의미 :

" 프로그래머 여러분, 최선을 다해서이 코드에 적절한 코드를 묶어주십시오 : 발명 "

완전성을 위해 과부하 란 다음을 의미합니다.

" 컴파일러 님 , 최선을 다해서이 이름에 적절한 코드를 바인딩하십시오 : 정렬 ".


추상 함수 는 본문을 가질 수 없으며 하위 클래스에 의해 재정의되어야합니다

가상 함수 는 몸체를 가지며 하위 클래스에 의해 무시 될 수도 있고 그렇지 않을 수도 있습니다.







virtual-functions