重载方法是什么? [英] Overloaded Method..why is base class given precedence?

查看:145
本文介绍了重载方法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在下面的代码中,我有一个重载的方法,一个参数类型ClazzA和另一个类型ClazzB。在显示的代码中,调用第一个GetDescription方法(将ClazzA作为参数的方法)。我想我理解为什么。

我的问题是...有一个优雅的方法,如果基础对象是类型classB(而不必检查每个对象,并投射它的方法, to clazzB)?

  public class ClazzA 
{
public virtual string Descr {get {returnA ; }}
}

public class ClazzB:ClazzA
{
public override string Descr {get {returnB; }}
}

public static class test
{
public static void Main()
{
ClazzA test = new ClazzB ;
GetDecription(test);
}

public static void GetDecription(ClazzA someClazz)
{
Debug.WriteLine(I am here);
}

public static void GetDecription(ClazzB someClazz)
{
Debug.WriteLine(I want to be here);
}
}

输出:I am here



我真的想要第二个方法被调用,因为'test'是类型ClassB。 Curerently我唯一的两个解决方案是:


  1. if(test is ClazzB)
    return GetDescription((ClazzB)测试);

    在ClassA中做几乎相同的事情...检查类型和委托给第二个方法

这两个都需要检查对象以确定其类型

解决方案

重载是在编译时确定的。引用的编译时类型为 ClazzA ,以便选择重载。你要求的是多个分派。 C#和许多其他语言(如C ++和Java)只支持单一分派(通过 virtual 方法)。人们有很多方法来解决这个问题。这样做的最纯粹的OO方式是访问者模式。您修改类以包含一个方法( Accept ),然后将 this 引用传递给访问者的方法访问)。这是因为您覆盖每个子类中的 Accept 方法,以使 this 将是对象的实际类型。所有访客需求都是您要支援的每个子类别的特定方法(详情请参阅维基百科)。

示例:

  public class ClazzA 
{
public virtual string Accept(ClassVisitor visitor)
{
return visitor.Visit(this);
}
}

public class ClazzB:ClazzA
{
public override string Accept(ClassVisitor visitor)
{
return visitor.Visit(this);
}
}

public abstract class ClassVisitor
{
public abstract string Visit(ClazzA a);
public abstract string Visit(ClazzB b);
}

public class GetDescriptionVisitor:ClassVisitor
{
public override string访问(ClazzA a)
{
returnA
}

public override string访问(ClazzB b)
{
returnB;
}
}

用法:

  ClassVisitor visitor = new GetDescriptionVisitor(); 
ClazzA b = new ClazzB();
Console.WriteLine(b.Accept(visitor)); // printsB


In the following code, i have an overloaded method, one that takes a parameter of type ClazzA and the other of type ClazzB. In the code shown, the first GetDescription method (the one that takes ClazzA as a parameter) is called. I think i understand why.
My question is..is there an elegant way of having the method that takes clazzB called first if the underlying object is of type classB (without having to inspect each object and casting it to clazzB)?

public class ClazzA
{
    public virtual string Descr { get { return "A"; } }
}

public class ClazzB : ClazzA
{
    public override string Descr { get { return "B"; } }
}

public static class test
{
    public static void Main()
    {
        ClazzA test = new ClazzB();
        GetDecription(test);
    }

    public static void GetDecription(ClazzA someClazz)
    {
        Debug.WriteLine("I am here");
    }

    public static void GetDecription(ClazzB someClazz)
    {
        Debug.WriteLine("I want to be here");
    }
}

Output: "I am here"

I really want the 2nd method to be called since 'test' is of type ClassB. Curerently the only two solutions i have is:

  1. if (test is ClazzB) return GetDescription( (ClazzB) test );

or

  1. In ClassA do pretty much the same thing...check the type and delegate to the 2nd method

Both of these require inspection of the object to determine its type

解决方案

Overloads are determined at compile time. The compile time type of the reference is ClazzA so that overload is chosen. What you are asking for is related to multiple dispatch. C# and many other languages like C++ and Java only support single dispatch (via virtual methods). There are a number of ways people have come up with to work around this. The purest OO way of doing this is the visitor pattern. You modify the classes to contain a method (Accept) which then passes the this reference to a method on the visitor (Visit). This works because you override the Accept method in each subclass so that this will be the object's actual type. All the visitor needs is a specific method for each subclass that you want to support (see wikipedia for more details).

A sample:

public class ClazzA
{
   public virtual string Accept(ClassVisitor visitor)
   {
      return visitor.Visit(this);
   }
}

public class ClazzB : ClazzA
{
   public override string Accept(ClassVisitor visitor)
   {
      return visitor.Visit(this);
   }
}

public abstract class ClassVisitor
{
  public abstract string Visit(ClazzA a);
  public abstract string Visit(ClazzB b);
}

public class GetDescriptionVisitor : ClassVisitor
{
    public override string Visit(ClazzA a)
    {
       return "A";
    }

    public override string Visit(ClazzB b)
    {
       return "B";
    }
}

Usage:

ClassVisitor visitor = new GetDescriptionVisitor();
ClazzA b = new ClazzB();
Console.WriteLine(b.Accept(visitor)); // prints "B"

这篇关于重载方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆