如何让派生类函数被执行?

发布于 2024-12-07 09:39:06 字数 1298 浏览 0 评论 0原文

我们有一个基类:Filter。 DistrFilter 和 ReportFilter 继承自 Filter。

在另一个类 FilterService.cs 中,我们有两个接受这三种类类型的函数。 FilterService 对 Filter 对象进行操作,但它不继承任何东西。

public class FilterService
{

  public string GetDesc(List<T> filters) where T : Filter
  {
     if(filters.Count == 0) return String.Empty;

     StringBuilder s = new StringBuilder("<ul>");
     foreach (T f in filters)
         s.AppendFormat("<li>{1}</li>", GetFilterText(f));

     s.Append("</ul>");

     return s.ToString();
  }

  public string GetFilterText(Filter f)
  {
     return "filter";
  }

  public string GetFilterText(DistrFilter f)
  {
     return "distr filter";
  }

  public string GetFilterText(ReportFilter f)
  {
     return "report filter";
  }
}

public static void main(string[] args)
{
   List<DistrFilter> distrFilters = new List<DistrFilters>();
   distrFilters.Add(new DistrFilter());
   distrFilters.Add(new DistrFilter());
   distrFilters.Add(new DistrFilter());

   FilterService fs = new FilterService();
   Console.WriteLine(fs.GetDescription(distrFilters));
}

然后打印:

  • 过滤器
  • 过滤器
  • ...

我怎样才能让它打印这个呢?

  • 分布过滤器
  • 分布过滤器
  • ...

We have a base class: Filter. DistrFilter and ReportFilter inherit from Filter.

In another class, FilterService.cs, we have two functions that accept these three class types. FilterService operates on Filter objects but it does not inherit from anything.

public class FilterService
{

  public string GetDesc(List<T> filters) where T : Filter
  {
     if(filters.Count == 0) return String.Empty;

     StringBuilder s = new StringBuilder("<ul>");
     foreach (T f in filters)
         s.AppendFormat("<li>{1}</li>", GetFilterText(f));

     s.Append("</ul>");

     return s.ToString();
  }

  public string GetFilterText(Filter f)
  {
     return "filter";
  }

  public string GetFilterText(DistrFilter f)
  {
     return "distr filter";
  }

  public string GetFilterText(ReportFilter f)
  {
     return "report filter";
  }
}

public static void main(string[] args)
{
   List<DistrFilter> distrFilters = new List<DistrFilters>();
   distrFilters.Add(new DistrFilter());
   distrFilters.Add(new DistrFilter());
   distrFilters.Add(new DistrFilter());

   FilterService fs = new FilterService();
   Console.WriteLine(fs.GetDescription(distrFilters));
}

Then it prints:

  • filter
  • filter
  • ...

How do I get it to print this instead?

  • distr filter
  • distr filter
  • ...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

倦话 2024-12-14 09:39:06

Filter 类添加一个虚拟方法,称为 GetName() 或类似的方法,并在 return "distr filter"; 中实现它code>DistrFilter 并在 ReportFilter 中作为 return "report filter"; 。然后只需在 GetDesc() 中调用 f.GetName() 即可。

或者,您可以在 GetDesc() 中使用诸如 if (f is DistrFilter) 之类的检查,但这种结构(显式检查特定派生类并以不同方式处理它们)是通常被认为是糟糕的设计。

Add a virtual method to the Filter class, called GetName() or something similar, and implement it as return "distr filter"; in DistrFilter and as return "report filter"; in ReportFilter. Then just call f.GetName() in GetDesc().

Alternatively, you could use checks like if (f is DistrFilter) in GetDesc(), but that sort of structure, explicitly checking for specific derived classes and handling them differently, is generally considered poor design.

如梦亦如幻 2024-12-14 09:39:06

要么将 GetFilterText() 实现为 Filter 中的虚拟方法:

class Filter
{
    // Can be converted into a property as well.
    public virtual string GetFilterText { return "filter"; }
}

class DistrFilter : Filter
{
    public override string GetFilterText { return "distr filter"; }
}

然后执行以下操作:

StringBuilder s = new StringBuilder("<ul>");
foreach (T f in filters)
    s.AppendFormat("<li>{0}</li>", f.GetFilterText());

或者如果您想将指定过滤器文本的问题与 Filter< 分开/code> 类,使用双重调度(访问者模式)。如果您可以拥有不同类型的过滤器服务,这将很有用。可以这样完成:

interface IServiceAcceptor
{
    string Accept(FilterService service);
}

public class Filter : IServiceAcceptor
{
    string IServiceAcceptor.Accept(FilterService service)
    {
        return service.GetFilterText(this);
    }   
}

public class DistrFilter : Filter, IServiceAcceptor
{
    string IServiceAcceptor.Accept(FilterService service)
    {
        return service.GetFilterText(this);
    }       
}

public class ReportFilter : Filter, IServiceAcceptor
{
    string IServiceAcceptor.Accept(FilterService service)
    {
        return service.GetFilterText(this);
    }       
}

然后在您的服务中:

  public string GetDesc<T>(List<T> filters) where T : IServiceAcceptor
  {
     if(filters.Count == 0) return String.Empty;

     var s = new StringBuilder("<ul>");
     foreach (T f in filters)
         s.AppendFormat("<li>{0}</li>", f.Accept(this));

     s.Append("</ul>");

     return s.ToString();
  }

一些参考:双重调度访客模式

Either implement GetFilterText() as a virtual method in Filter:

class Filter
{
    // Can be converted into a property as well.
    public virtual string GetFilterText { return "filter"; }
}

class DistrFilter : Filter
{
    public override string GetFilterText { return "distr filter"; }
}

Then do this:

StringBuilder s = new StringBuilder("<ul>");
foreach (T f in filters)
    s.AppendFormat("<li>{0}</li>", f.GetFilterText());

Or if you want to separate the concern of specifying the filter text from the Filter classes, use double dispatch (visitor pattern). This is useful if you can have different types of filter services. This can be done this way:

interface IServiceAcceptor
{
    string Accept(FilterService service);
}

public class Filter : IServiceAcceptor
{
    string IServiceAcceptor.Accept(FilterService service)
    {
        return service.GetFilterText(this);
    }   
}

public class DistrFilter : Filter, IServiceAcceptor
{
    string IServiceAcceptor.Accept(FilterService service)
    {
        return service.GetFilterText(this);
    }       
}

public class ReportFilter : Filter, IServiceAcceptor
{
    string IServiceAcceptor.Accept(FilterService service)
    {
        return service.GetFilterText(this);
    }       
}

Then in your service:

  public string GetDesc<T>(List<T> filters) where T : IServiceAcceptor
  {
     if(filters.Count == 0) return String.Empty;

     var s = new StringBuilder("<ul>");
     foreach (T f in filters)
         s.AppendFormat("<li>{0}</li>", f.Accept(this));

     s.Append("</ul>");

     return s.ToString();
  }

Some references: Double dispatch, Visitor Pattern

沉睡月亮 2024-12-14 09:39:06

实现一个执行如下操作的模式:

public class Filter
{
    public virtual string GetDescription()
    {
        return "filter";
    }
}

public class DistrFilter : Filter
{
    public override string GetDescription()
    {
        return "distr filter";
    }
}
public class ReportFilter : Filter
{
    public override string GetDescription()
    {
        return "report filter";
    }
}

public class FilterService
{
    public string GetDescription<T>( List<T> filters )
        where T: Filter
    {
        if ( filters.Count == 0 )
            return String.Empty;

        StringBuilder s = new StringBuilder( "<ul>" );
        foreach ( T f in filters )
            s.AppendFormat( "<li>{0}</li>", f.GetDescription() );

        s.Append( "</ul>" );

        return s.ToString();
    }
}

Implement a pattern that does something like this:

public class Filter
{
    public virtual string GetDescription()
    {
        return "filter";
    }
}

public class DistrFilter : Filter
{
    public override string GetDescription()
    {
        return "distr filter";
    }
}
public class ReportFilter : Filter
{
    public override string GetDescription()
    {
        return "report filter";
    }
}

public class FilterService
{
    public string GetDescription<T>( List<T> filters )
        where T: Filter
    {
        if ( filters.Count == 0 )
            return String.Empty;

        StringBuilder s = new StringBuilder( "<ul>" );
        foreach ( T f in filters )
            s.AppendFormat( "<li>{0}</li>", f.GetDescription() );

        s.Append( "</ul>" );

        return s.ToString();
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文