아래 코드에서 두 가지 방법으로 부모 메소드 인 methodTwo에 액세스하려고 시도했지만 결과는 항상 2였습니다.이 두 클래스를 수정하지 않고 ChildClass 인스턴스에서 1 개의 결과를 얻는 방법이 있습니까?
class ParentClass
{
public int methodOne()
{
return methodTwo();
}
virtual public int methodTwo()
{
return 1;
}
}
class ChildClass : ParentClass
{
override public int methodTwo()
{
return 2;
}
}
class Program
{
static void Main(string[] args)
{
var a = new ChildClass();
Console.WriteLine("a.methodOne(): " + a.methodOne());
Console.WriteLine("a.methodTwo(): " + a.methodTwo());
Console.WriteLine("((ParentClass)a).methodTwo(): "
+ ((ParentClass)a).methodTwo());
Console.ReadLine();
}
}
최신 정보ChrisW가 올린 글 :
수업 외에서 나는 잘 모른다. 어떤 쉬운 방법; 하지만 아마도, 나는하지 않습니다. 시도하면 어떻게되는지 알 수 있습니다. reflection : Type.GetMethod를 사용하십시오. methodInfo를 찾는 메소드 에있는 방법과 관련된 ParentClass를 호출 한 다음 호출 MethodInfo.Invoke
그 대답은 삭제되었습니다. 그 호크가 호기심에 효과가 있는지 궁금합니다.
일리노이 수준에서 아마 당신은call
오히려callvirt
, 그리고 일을 끝내라 - 그러나 우리가 C #으로 제한된다면, -p (편집하다꿰매다! 런타임이 멈 춥니 다.VerificationException
: "작업으로 인해 런타임이 불안정해질 수 있습니다."; 그 사람을 제거하다virtual
그리고 그것은 잘 작동합니다. 반으로 너무 영리 해 ...)
내부ChildClass
유형, 당신은 사용할 수 있습니다base.methodTwo()
- 그러나 이것은 외부에서 가능하지 않습니다. 한 단계 이상 내려갈 수 없습니까?base.base.Foo()
지원하다.
그러나 메소드 숨기기를 사용하여 다형성을 비활성화하면대답당신이 원하지만, 나쁜 이유로 :
class ChildClass : ParentClass
{
new public int methodTwo() // bad, do not do
{
return 2;
}
}
변수가 정의되어 있는지 여부에 따라 동일한 객체에서 다른 답변을 얻을 수 있습니다.ChildClass
또는ParentClass
.
new
이 시나리오에서는 유형을보다 전문화하기위한 것입니다. 예를 들어,DbCommand
~을 가지고있다.public DbParameterCollection Parameters {get;}
-하지만SqlCommand : DbCommand
~을 가지고있다.public new SqlParameterCollection Parameters {get;}
. 두 API 모두 동일한 값을 반환합니다.예(별도의protected abstract
속성, 즉DbParameterCollection
- 그 값은 항상있다에이SqlParameterCollection
) -보다 구체적인 유형은보다 구체적인 방식으로 그것을 노출합니다 - Marc Gravell♦
내면에ChildClass.methodTwo()
, 전화해도됩니다base.methodTwo()
.
수업 외부, 전화((ParentClass)a).methodTwo())
의지요구ChildClass.methodTwo
. 이것이 가상의 방법이 존재하는 전체 이유입니다.
위에서 언급했듯이 PRODUCTION 코드에서 "base.base"를 호출해야하는 경우 클래스 디자인에 문제가 있습니다. 그러나 컴파일 할 수없는 외부 라이브러리를 사용하면서 일부 작업장을 디버깅하거나 검색하는 경우이 기술을 사용하는 것이 합법적입니다. C #이이 옵션을 직접 제공하지 않는다는 것은 좋지 않습니다. 아직도 당신은 일리노이 발전기와 Emit과 Kenneth Xu 솔루션을 사용할 수 있습니다. 그것은 작동합니다.
class A { public virtual string foo() { return "A"; } }
class B : A { public override string foo() { return "B"; } }
// now in class C
class C : B {}
// we can call virtual method "foo" from A using following code
MethodInfo fooA = typeof(A).GetMethod("foo", BindingFlags.Public | BindingFlags.Instance);
DynamicMethod baseBaseFoo = new DynamicMethod(
"foo_A",
typeof(string),
new[] { typeof(A) },
typeof(A));
ILGenerator il = baseBaseFoo.GetILGenerator();
il.Emit(OpCodes.Ldarg, 0);
il.EmitCall(OpCodes.Call, fooA, null);
il.Emit(OpCodes.Ret);
// call foo() from class A, it returns "A"
(string)baseBaseFoo.Invoke(null, new object[] { this });
참조 용 샘플 및 전체 샘플http://kennethxu.blogspot.cz/2009/05/cnet-calling-grandparent-virtual-method.html
Kenneth Xu 감사합니다!
Mark Gravell이 말했듯이, 아니, 외부 적으로는 아닙니다. 하지만 여기 제가 사용한 또 다른 해킹이 있습니다.ChildClass
폭로 할 수있다.methodTwo()
~로부터ParentClass
자체 사용 또는 외부 사용을 위해. 귀하의 경우 :
class ChildClass : ParentClass {
override public int methodTwo() {
return 2;
}
public int ParentClass_methodTwo() {
return base.methodTwo();
}
}
// Now instead of
Console.WriteLine("ParentClass methodTwo: " + ((ParentClass)a).methodTwo());
// use
Console.WriteLine("ParentClass methodTwo: " + a.ParentClass_methodTwo());
필자의 경우, 자식 클래스는 피어 (peer) 개념을 도입했으며,methodTwo()
피어에서 기본 버전을 호출합니다. 그러나 그것을 오버라이드하여 숨겼습니다 ... 아니면 그랬습니까? 이 기술은 구조에 왔습니다.
class ChildClass : ParentClass {
ChildClass peer;
override public int methodTwo() {
return peer.ParentClass_methodTwo();
}
private int ParentClass_methodTwo() {
return base.methodTwo();
}
}
public class Parent
{
public string Method()
{
return "parent";
}
}
public class Child:Parent
{
public string Method()
{
return "child";
}
}
위의 코드는 부모 메서드의 값을 성공적으로 재정의하지만 여전히 부모 메서드의 값을 변경하지 않습니다.
둘 다에서 값을 반환 할 수 있습니다.학급과하위 클래스아래 코드 사용 -
Child child = new Child();
string result = (((Parent)child).Method()) + child.Method();
그러나 Visual Studio는 컴파일 타임에 경고를 표시합니다.
내 지식으로는 일단 메소드가 오버라이드되면 부모 메소드를 호출 할 수 없다.
ParentClass의 인스턴스를 직접 작성하지 않으면 불가능하다고 생각합니다. 그게 바로 상속, 다형성의 본질 ...
나는이 도움을 찾다가 우연히 발견했고, 조상의 방법을 호출하는 방법으로 끝을 맺었다. 이는 조상 클래스를 편집 할 수 있다고 가정하는 해결 방법입니다.
상위 클래스에있는 문제의 기능을 필요한 매개 변수와 함께 정적 메서드에 넣습니다. 이 클래스의 메서드는 기능을 복제 할 필요가 없도록 호출 할 수 있으며 자식 클래스는 필요한 경우 정적 메서드를 통해 해당 기능을 호출 할 수 있습니다. 그렇게하면 메서드 내에서도 수행 할 수 있으며 호출 할 특정 클래스를 인용 할 수 있습니다. 또한, 그것은 단순한 부모보다 더 먼 선조들에 접근 할 수 있는데, 이것은 "기본"의 사용 제한이다.