program tip

가상 방법이란 무엇입니까?

radiobox 2020. 11. 4. 07:51
반응형

가상 방법이란 무엇입니까?


메소드를 "가상"으로 선언하는 이유는 무엇입니까?

가상을 사용하면 어떤 이점이 있습니까?


가상 수정이 방법 \ 속성 (요법)을 사용하여 도출 된 클래스에서 변형 될 수 있다는 표시로 이용된다 오버라이드 개질제.

예:

class A
{
    public virtual void Foo()
       //DoStuff For A
}

class B : A
{
    public override void Foo()
    //DoStuff For B

    //now call the base to do the stuff for A and B 
    //if required
    base.Foo()
}

Virtual을 사용하면 상속하는 클래스가 기본 클래스가 사용하는 메서드를 대체 할 수 있습니다.

public class Thingy
{
    public virtual void StepA()
    {
        Console.Out.WriteLine("Zing");
    }

    public void Action()
    {
        StepA();
        Console.Out.WriteLine("A Thingy in Action.");
    }
}

public class Widget : Thingy
{
    public override void StepA()
    {
        Console.Out.WriteLine("Wiggy");
    }
}

class Program
{
    static void Main(string[] args)
    {
        Thingy thingy = new Thingy();
        Widget widget = new Widget();

        thingy.Action();
        widget.Action();

        Console.Out.WriteLine("Press any key to quit.");
        Console.ReadKey();
    }
 }

프로그램을 실행할 때 출력은 다음과 같습니다.

Zing 
A Thingy in Action. 
Wiggy 
A Thingy in Action.

Widget이 Thingy 수준에서 정의 된 Action () 메서드를 호출했지만 내부적으로 Thingy가 Widget의 StepA () 메서드를 호출 한 방법에 주목하십시오.

기본적인 대답은 클래스 상속자에게 더 많은 유연성을 제공한다는 것입니다. 물론 수업을 잘 설계해야합니다. 그렇지 않으면 약한 혼란이 생길 ​​수 있습니다.


가상 메서드는 실제 메서드 호출이 기본 개체의 런타임 유형에 따라 달라지는 메서드 유형입니다.

비가 상 메서드는 호출되는 실제 메서드가 메서드 호출 시점에서 개체의 참조 형식에 따라 달라지는 메서드 유형입니다.


MSDN의 가상 방법

virtual 키워드는 메서드 또는 속성 선언을 수정하는 데 사용되며,이 경우 메서드 또는 속성을 가상 멤버라고합니다. 가상 멤버의 구현은 파생 클래스의 재정의 멤버에 의해 변경 될 수 있습니다.

가상 메서드가 호출되면 개체의 런타임 유형에서 재정의 멤버를 확인합니다. 가장 많이 파생 된 클래스의 재정의 멤버가 호출되며 파생 클래스가 멤버를 재정의하지 않은 경우 원래 멤버 일 수 있습니다. (런타임 유형 및 대부분의 파생 된 구현에 대한 자세한 내용은 10.5.3 가상 메서드를 참조하십시오.)

기본적으로 메서드는 가상이 아닙니다. 비가 상 메서드는 재정의 할 수 없습니다.

다음 수정 자와 함께 가상 수정자를 사용할 수 없습니다.

정적 추상 재정의

가상 속성은 선언 및 호출 구문의 차이를 제외하고 추상 메서드처럼 작동합니다.

  • 정적 속성에 가상 수정자를 사용하는 것은 오류입니다.
  • 상속 된 가상 속성은 override 한정자를 사용하는 속성 선언을 포함하여 파생 클래스에서 재정의 할 수 있습니다.

클래스에서 파생 할 계획이 없더라도 클래스를 모의하기 위해 가상 메서드를 표시해야 할 수 있습니다. 일부 모의 프레임 워크는 가상 메서드를 모의하는 것만 허용합니다. 인터페이스를 구현하는 메서드는 암시 적으로 가상입니다.

저는 이러한 제한이있는 RhinoMocks를 사용하고 있으며 이러한 이유로 기본적으로 내 메서드를 가상으로 표시했습니다. 저에게있어 상속이 시작되는 경우가 훨씬 적기 때문에 가상 메서드를 사용하는 가장 큰 이유 일 것입니다.


가상 메서드는 파생 클래스에 대한 구현이 선택 사항이라는 점을 제외하면 기본 클래스의 추상 메서드와 유사합니다. 또한 논리를 가상 메서드에 넣고 파생 클래스에서 재정의 할 수 있습니다.


상속 클래스에서 재정의 할 수 있습니다.

키워드에 대한 MSDN 항목확인하십시오 . 그것은 더 깊이 설명합니다.


짧은 질문, 짧은 답변! 자신이 속한 클래스를 상속 할 것이라고 생각되면 메서드를 "가상"으로 한정하십시오.

더 긴 답변 : "가상을 사용하면 파생 클래스에서 메서드의 또 다른 의미를 제공하기 위해 재정의 할 수 있습니다.


말할 필요도없이, 가상 메서드는 코드가 개방형 폐쇄 원칙 을 준수하려고 할 때 유용합니다.

열기 휴일 원리에 대한 자세한 내용을 여기에 , 삼촌 밥의 원래 OCP 백서.

또한 pls 는 Java와 달리 C #에서 메소드가 기본적으로 가상 아님을 알고 있습니다 .


여기에서는 예제 C # Virtual Method로 명확하게 설명합니다.


가상 함수는 실제로 존재하지 않는 함수입니다. 파생 클래스는 가상 함수를 재정 의하여 수정할 수 있습니다. 가상 함수는 런타임 다형성을 달성하는 방법 중 하나입니다.

    public class sample {
      public virtual void fun(){
        Console.WriteLine("base sample class \n");
      }
    }
    public class A : sample{
      public override void fun(){
        Console.WriteLine("Class A \n");
      }
    }
    public class B : sample{
      public override void fun(){
        Console.WriteLine("Class B \n");
      }
    }
    class run{
      public static void main(String[] args){
        sample obj = new sample();
        sample obj1 = new A();
        sample obj2 = new B();
        obj.fun();
        obj1.fun();
        obj2.fun();
      }
    }

런타임은 컴파일 시간 동안 발생합니다.
메서드를 가상으로 선언 할 때 파생 클래스에서 선언하려면 override또는 new수정자를 추가해야합니다 .
우리는 TrySpeak. 자식과 아버지를 전달하면 모두 Speak of father를 TryScream호출하고는 각 메서드를 호출합니다.
이를 이해하기 위해 우리가 알아야 할 몇 가지 사항이 있습니다. Child 인스턴스에는 ScreamChild 클래스 또는 Father 클래스의 두 가지 메서드 가 있습니다 . Screamfrom Child 클래스 나 Father 클래스 를 호출 할 수 있습니다 . VirtaulModifier는 파생 클래스에 의해 재정의 될 수 있도록 메서드를 표시 하기 때문에이 메서드 Scream는 Father 클래스에서 호출되는 경우에도 재정의되므로 새 수정자를 사용하면 달라집니다.

import system;
class Father
{
    Speak()
    {
        Console.Writeline("Father is speaking") 
    }
    virtual Scream()
    {
        Console.Writeline("Father is screaming")    
    }
}
class Child: father
{
    Speak()
    {
        Console.Writeline("Child is speaking")  
    }
    override Scream()
    {
        Console.Writeline("Child is screaming") 
    }
}
class APP
{
    public static void Main()
    {
        // We new two instances here
        Father father = new Father();
        Child child = new Child();        
        // Here we call their scream or speak through TryScream or TrySpeak
        TrySpeak(father);
        TrySpeak(child);
        //>>>"Father is speaking"
        //>>>"Father is speaking"
        TryScream(father);
        TryScream(child);
        //>>>"Father is screaming"
        //>>>"Child is screaming"
    }
    // when your method take an Parameter who type is Father
    // You can either pass in a Father instance or
    // A instance of a derived Class from Father
    // which could be Child
    public static void TrySpeak(Father person)
    {
        person.Scream();
    }
    public static void TryScream(Father person)
    {
        person.Speak();
    }
}

가상 및 비가 상 방법의 차이.

두 개의 클래스가 있습니다. 하나는 Vehicle 클래스이고 다른 하나는 Cart 클래스입니다. "Vehicle"클래스는 두 가지 메서드가있는 기본 클래스입니다. 하나는 가상 메서드 "Speed ​​()"이고 다른 하나는 비가 상 메서드 "Average ()"입니다. 따라서 기본 클래스 가상 메서드 "Speed ​​()"는 하위 클래스에서 재정의됩니다. 하위 클래스 "Cart"의 인스턴스를 생성하고 해당 인스턴스가 기본 클래스 "Vehicle"유형에 할당되는 진입 점이있는 "Program"클래스 (실행 클래스)가 하나 더 있습니다. 두 클래스의 인스턴스에 의해 가상 및 비가 상 메서드를 호출하면 실행 유형에 따라 인스턴스 가상 메서드 구현이 호출됩니다. 즉, 두 클래스 '

using System;

namespace VirtualExample
{   
    class Vehicle
    {   
       public double distance=0.0;
       public double hour =0.0;
       public double fuel =0.0; 

       public Vehicle(double distance, double hour, double fuel)
       {
           this.distance = distance;
           this.hour = hour;
           this.fuel = fuel;
       }

       public void Average()
       {
           double average = 0.0;
           average = distance / fuel;
           Console.WriteLine("Vehicle Average is {0:0.00}", average);
       }

       public virtual void Speed()
       {
           double speed = 0.0;
           speed = distance / hour;
           Console.WriteLine("Vehicle Speed is {0:0.00}", speed);
       }
    } 

    class Car : Vehicle
    {
        public Car(double distance, double hour, double fuel)
            : base(distance, hour, fuel)
        {
        }
      public void Average()
        {
            double average = 0.0;
            average = distance / fuel;
            Console.WriteLine("Car Average is {0:0.00}", average);
        }

        public override void Speed()
        {
            double speed = 0.0;           
            speed = distance / hour;
            Console.WriteLine("Car Speed is {0:0.00}", speed);
        }
    } 

    class Program
   {
        static void Main(string[] args)
        {
             double distance,hour,fuel=0.0;
             Console.WriteLine("Enter the Distance");
             distance = Double.Parse(Console.ReadLine());
             Console.WriteLine("Enter the Hours");
             hour = Double.Parse(Console.ReadLine());
             Console.WriteLine("Enter the Fuel");
             fuel = Double.Parse(Console.ReadLine());
             Car objCar = new Car(distance,hour,fuel);
             Vehicle objVeh = objCar;
             objCar.Average();
             objVeh.Average();
             objCar.Speed();
             objVeh.Speed();
            Console.Read();
        }       
    }
}

여기에 이미지 설명 입력

도움을 드리겠습니다!


C #에서 파생 클래스의 기본 클래스 메서드를 재정의하려면 아래와 같이 기본 클래스 메서드를 가상으로 선언하고 파생 클래스 메서드를 재정의로 선언해야합니다.

using System;
namespace Polymorphism
{
 class A
 {
 public virtual void Test() { Console.WriteLine("A::Test()"); }
 }

 class B : A
 {
 public override void Test() { Console.WriteLine("B::Test()"); }
 }

 class C : B
 {
 public override void Test() { Console.WriteLine("C::Test()"); }
 }

 class Program
 {
 static void Main(string[] args)
 {

 A a = new A();
 B b = new B();
 C c = new C();
 a.Test(); // output --> "A::Test()"
 b.Test(); // output --> "B::Test()"
 c.Test(); // output --> "C::Test()"

 a = new B();
 a.Test(); // output --> "B::Test()"

 b = new C();
 b.Test(); // output --> "C::Test()"

 Console.ReadKey();
 }
 }
}

파생 클래스의 메서드는 동시에 가상 및 새 메서드가 될 수 있으므로 virtual 및 new 키워드를 사용하여 메서드 숨김과 메서드 재정의를 혼합 할 수도 있습니다. 아래와 같이 클래스 C의 클래스 B, Test () 메서드를 재정의 할 때 파생 된 클래스 메서드를 다음 수준으로 추가 재정의하려는 경우 필요합니다.

using System;
namespace Polymorphism
{
 class A
 {
 public void Test() { Console.WriteLine("A::Test()"); }
 }

 class B : A
 {
 public new virtual void Test() { Console.WriteLine("B::Test()"); }
 }

 class C : B
 {
 public override void Test() { Console.WriteLine("C::Test()"); }
 }

 class Program
 {
 static void Main(string[] args)
 {

 A a = new A();
 B b = new B();
 C c = new C();

 a.Test(); // output --> "A::Test()"
 b.Test(); // output --> "B::Test()"
 c.Test(); // output --> "C::Test()"

 a = new B();
 a.Test(); // output --> "A::Test()"

 b = new C();
 b.Test(); // output --> "C::Test()"

 Console.ReadKey();
 }
 }
}

황금 단어 : 가상 키워드는 기본 클래스에서 선언 된 메서드, 속성, 인덱서 또는 이벤트를 수정하고 파생 클래스에서 재정의 할 수 있도록하는 데 사용됩니다.

override 키워드는 가상 / 추상 메서드, 속성, 인덱서 또는 기본 클래스의 이벤트를 파생 클래스로 확장하거나 수정하는 데 사용됩니다.

new 키워드는 기본 클래스의 메서드, 속성, 인덱서 또는 이벤트를 파생 클래스로 숨기는 데 사용됩니다.

즐겨 :-)


이 링크는 매우 쉬운 예제 https://stackoverflow.com/a/2392656/3373865로 더 나은 이해를 제공합니다.

참고 URL : https://stackoverflow.com/questions/622132/what-are-virtual-methods

반응형