program story

base.base.method ()를 호출하는 방법?

inputbox 2020. 8. 9. 10:24
반응형

base.base.method ()를 호출하는 방법?


// Cannot change source code
class Base
{
    public virtual void Say()
    {
        Console.WriteLine("Called from Base.");
    }
}

// Cannot change source code
class Derived : Base
{
    public override void Say()
    {
        Console.WriteLine("Called from Derived.");
        base.Say();
    }
}

class SpecialDerived : Derived
{
    public override void Say()
    {
        Console.WriteLine("Called from Special Derived.");
        base.Say();
    }
}

class Program
{
    static void Main(string[] args)
    {
        SpecialDerived sd = new SpecialDerived();
        sd.Say();
    }
}

결과는 다음과 같습니다.

Special Derived에서 호출되었습니다.
Derived에서 호출되었습니다. / * 이것은 예상되지 않습니다 * /
Base에서 호출됩니다.

중산층 "Derived"의 메서드가 호출되지 않도록 SpecialDerived 클래스를 어떻게 다시 작성할 수 있습니까?

업데이트 : Base 대신 Derived에서 상속하려는 이유는 Derived 클래스에 다른 많은 구현이 포함되어 있기 때문입니다. base.base.method()여기서 할 수 없기 때문에 가장 좋은 방법은 다음을 수행하는 것입니까?

// 소스 코드를 변경할 수 없습니다.

class Derived : Base
{
    public override void Say()
    {
        CustomSay();

        base.Say();
    }

    protected virtual void CustomSay()
    {
        Console.WriteLine("Called from Derived.");
    }
}

class SpecialDerived : Derived
{
    /*
    public override void Say()
    {
        Console.WriteLine("Called from Special Derived.");
        base.Say();
    }
    */

    protected override void CustomSay()
    {
        Console.WriteLine("Called from Special Derived.");
    }
}

이것은 나쁜 프로그래밍 관행이며 C #에서는 허용되지 않습니다. 그것은 나쁜 프로그래밍 관행입니다.

  • 그랜드베이스의 세부 사항은베이스의 구현 세부 사항입니다. 당신은 그들에게 의존해서는 안됩니다. 기본 클래스는 그랜드베이스 위에 추상화를 제공합니다. 이를 피하기 위해 우회를 구축하는 것이 아니라 추상화를 사용해야합니다.

  • 당신은 그것이하는 일을 좋아하고 재사용하고 확장하기를 원하기 때문에 당신의 기지에서 파생되었습니다. 그것이하는 일이 마음에 들지 않고 함께 일하는 것보다 그것을 해결하고 싶다면, 왜 처음부터 그 일에서 파생 되었습니까? 그 기능이 사용하고 확장하려는 경우 그랜드베이스에서 직접 파생하십시오.

  • 기본은 기본이 그랜드베이스의 방법을 사용하는 방법에 대한 세부 사항에 의해 유지되는 보안 또는 의미 적 일관성 목적을 위해 특정 불변성을 요구할 수 있습니다. 기본의 파생 클래스가 이러한 불변성을 유지하는 코드를 건너 뛰도록 허용하면 기본이 일관성이없고 손상된 상태가 될 수 있습니다.


사람들이 많은 시간이 지난 후에도 여전히이 질문에 답하기 때문에 여기에 추가하고 싶습니다. 물론 나쁜 습관이지만 원칙적으로 작성자가 원하는 것을 수행하는 것은 여전히 ​​가능합니다.

class SpecialDerived : Derived
{
    public override void Say()
    {
        Console.WriteLine("Called from Special Derived.");
        var ptr = typeof(Base).GetMethod("Say").MethodHandle.GetFunctionPointer();            
        var baseSay = (Action)Activator.CreateInstance(typeof(Action), this, ptr);
        baseSay();            
    }
}

C #에서는 할 수 없습니다. IL에서는 실제로 지원됩니다. 부모 클래스에 가상이 아닌 호출을 할 수 있습니다 ...하지만하지 마십시오. :)


대답은 (당신이 찾고있는 것이 아님을 알고 있습니다) :

class SpecialDerived : Base
{
    public override void Say()
    {
        Console.WriteLine("Called from Special Derived.");
        base.Say();
    }
}

사실, 당신은 상속받은 클래스와 직접적인 상호 작용 만 할 수 있습니다. 해당 클래스를 계층으로 생각하십시오. 파생 클래스에 원하는만큼 또는 부모의 기능을 제공하는 것입니다.

편집하다:

귀하의 편집은 작동하지만 다음과 같은 것을 사용할 것이라고 생각합니다.

class Derived : Base
{
    protected bool _useBaseSay = false;

    public override void Say()
    {
        if(this._useBaseSay)
            base.Say();
        else
            Console.WriteLine("Called from Derived");
    }
}

물론 실제 구현에서는 확장 성과 유지 관리를 위해 다음과 같은 작업을 수행 할 수 있습니다.

class Derived : Base
{
    protected enum Mode
    {
        Standard,
        BaseFunctionality,
        Verbose
        //etc
    }

    protected Mode Mode
    {
        get; set;
    }

    public override void Say()
    {
        if(this.Mode == Mode.BaseFunctionality)
            base.Say();
        else
            Console.WriteLine("Called from Derived");
    }
}

그러면 파생 클래스가 부모의 상태를 적절하게 제어 할 수 있습니다.


단순히 자식 클래스를 특정 부모 클래스로 캐스팅하고 특정 구현을 호출하지 않는 이유는 무엇입니까? 이것은 특수한 상황이며 특수한 경우 솔루션을 사용해야합니다. new그래도 자식 메서드 에서는 키워드 를 사용해야합니다 .

public class SuperBase
{
    public string Speak() { return "Blah in SuperBase"; }
}

public class Base : SuperBase
{
    public new string Speak() { return "Blah in Base"; }
}

public class Child : Base
{
    public new string Speak() { return "Blah in Child"; }
}

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        Child childObj = new Child();

        Console.WriteLine(childObj.Speak());

        // casting the child to parent first and then calling Speak()
        Console.WriteLine((childObj as Base).Speak()); 

        Console.WriteLine((childObj as SuperBase).Speak());
    }
}

그랜드베이스 함수를 호출하기 위해 첫 번째 수준 파생 클래스에서 간단한 함수를 만들 수도 있습니다.


public class A
{
    public int i = 0;
    internal virtual void test()
    {
        Console.WriteLine("A test");
    }
}

public class B : A
{
    public new int i = 1;
    public new void test()
    {
        Console.WriteLine("B test");
    }
}

public class C : B
{
    public new int i = 2;
    public new void test()
    {
        Console.WriteLine("C test - ");
        (this as A).test(); 
    }
}

이에 대한 내 2c는 툴킷 클래스에서 호출하는 데 필요한 기능을 구현하고 필요한 곳에서 호출하는 것입니다.

// Util.cs
static class Util 
{
    static void DoSomething( FooBase foo ) {}
}

// FooBase.cs
class FooBase
{
    virtual void Do() { Util.DoSomething( this ); }
}


// FooDerived.cs
class FooDerived : FooBase
{
    override void Do() { ... }
}

// FooDerived2.cs
class FooDerived2 : FooDerived
{
    override void Do() { Util.DoSomething( this ); }
}

이것은 접근 권한에 대한 약간의 생각이 필요하며 internal, 기능을 용이하게하기 위해 접근 자 메서드를 추가해야 할 수도 있습니다.


파생 클래스 소스에 액세스 할 수 없지만 현재 메서드 외에 파생 클래스의 모든 소스가 필요한 경우 파생 클래스를 수행하고 파생 클래스의 구현을 호출하는 것이 좋습니다.

예를 들면 다음과 같습니다.

//No access to the source of the following classes
public class Base
{
     public virtual void method1(){ Console.WriteLine("In Base");}
}
public class Derived : Base
{
     public override void method1(){ Console.WriteLine("In Derived");}
     public void method2(){ Console.WriteLine("Some important method in Derived");}
}

//Here should go your classes
//First do your own derived class
public class MyDerived : Base
{         
}

//Then derive from the derived class 
//and call the bass class implementation via your derived class
public class specialDerived : Derived
{
     public override void method1()
     { 
          MyDerived md = new MyDerived();
          //This is actually the base.base class implementation
          MyDerived.method1();  
     }         
}

이전 게시물에서 볼 수 있듯이 클래스 기능을 우회해야하는 경우 클래스 아키텍처에 문제가 있다고 주장 할 수 있습니다. 그것은 사실 일 수 있지만, 대규모의 성숙한 프로젝트에서 클래스 구조를 항상 재구성하거나 리팩토링 할 수는 없습니다. 다양한 수준의 변경 관리가 하나의 문제 일 수 있지만, 리팩토링 후에도 기존 기능을 동일하게 유지하는 것이 항상 간단한 작업은 아닙니다. 특히 시간 제약이 적용되는 경우 더욱 그렇습니다. 성숙한 프로젝트에서는 코드 재구성 후 다양한 회귀 테스트가 통과하지 못하도록하는 것이 상당히 작업이 될 수 있습니다. 종종 나타나는 모호한 "이상 함"이 있습니다. 상속 된 기능이 실행되지 않아야하는 경우 (또는 다른 작업을 수행해야하는 경우) 유사한 문제가 발생했습니다. 우리가 아래에서 따랐던 접근 방식, 제외해야 할 기본 코드를 별도의 가상 기능에 넣는 것이 었습니다. 그런 다음이 함수는 파생 클래스에서 재정의되고 기능이 제외되거나 변경 될 수 있습니다. 이 예제에서 "Text 2"는 파생 클래스에서 출력되지 않도록 할 수 있습니다.

public class Base
{
    public virtual void Foo()
    {
        Console.WriteLine("Hello from Base");
    }
}

public class Derived : Base
{
    public override void Foo()
    {
        base.Foo();
        Console.WriteLine("Text 1");
        WriteText2Func();
        Console.WriteLine("Text 3");
    }

    protected virtual void WriteText2Func()
    {  
        Console.WriteLine("Text 2");  
    }
}

public class Special : Derived
{
    public override void WriteText2Func()
    {
        //WriteText2Func will write nothing when 
        //method Foo is called from class Special.
        //Also it can be modified to do something else.
    }
}

There seems to be a lot of these questions surrounding inheriting a member method from a Grandparent Class, overriding it in a second Class, then calling its method again from a Grandchild Class. Why not just inherit the grandparent's members down to the grandchildren?

class A
{
    private string mystring = "A";    
    public string Method1()
    {
        return mystring;
    }
}

class B : A
{
    // this inherits Method1() naturally
}

class C : B
{
    // this inherits Method1() naturally
}


string newstring = "";
A a = new A();
B b = new B();
C c = new C();
newstring = a.Method1();// returns "A"
newstring = b.Method1();// returns "A"
newstring = c.Method1();// returns "A"

Seems simple....the grandchild inherits the grandparents method here. Think about it.....that's how "Object" and its members like ToString() are inherited down to all classes in C#. I'm thinking Microsoft has not done a good job of explaining basic inheritance. There is too much focus on polymorphism and implementation. When I dig through their documentation there are no examples of this very basic idea. :(


If you want to access to base class data you must use "this" keyword or you use this keyword as reference for class.

namespace thiskeyword
{
    class Program
    {
        static void Main(string[] args)
        {
            I i = new I();
            int res = i.m1();
            Console.WriteLine(res);
            Console.ReadLine();
        }
    }

    public class E
    {
        new public int x = 3;
    }

    public class F:E
    {
        new public int x = 5;
    }

    public class G:F
    {
        new public int x = 50;
    }

    public class H:G
    {
        new public int x = 20;
    }

    public class I:H
    {
        new public int x = 30;

        public int m1()
        {
           // (this as <classname >) will use for accessing data to base class

            int z = (this as I).x + base.x + (this as G).x + (this as F).x + (this as E).x; // base.x refer to H
            return z;
        }
    }
}

참고URL : https://stackoverflow.com/questions/2323401/how-to-call-base-base-method

반응형