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
'program story' 카테고리의 다른 글
수 파이프-각도 2의 매개 변수는 무엇입니까? (0) | 2020.08.09 |
---|---|
Android 에뮬레이터는 SQLite 데이터베이스를 어디에 저장합니까? (0) | 2020.08.09 |
JodaTime으로 특정 달의 마지막 날짜를 얻는 방법은 무엇입니까? (0) | 2020.08.09 |
asp.net MVC 4 및 MVC 5에서 기본 컨트롤러를 설정하는 방법 (0) | 2020.08.09 |
런타임 중에 방향을 잠그는 방법 (0) | 2020.08.08 |