当我们尝试通过继承重用代码时如何解决并行继承层次结构

发布于 2025-01-09 14:49:43 字数 195 浏览 0 评论 0原文

最近在一次求职面试中,他们问我“当我们尝试通过继承重用代码时如何解决并行继承层次结构”。我想到了聚合组合,但我对基于此做一个例子感到有点困惑。

所以我决定留待以后加深概念,但经过调查后并没有最终形成该问题的精确答案,有人可以向我解释一个解决方案或一个例子吗?

Recently in a job interview, they ask me "how to solve Parallel Inheritance Hierarchies when we try to reuse code through inheritance". I thought on Aggregation or Composition, but i was a little confused on making an example based on that.

So I decided to leave it pending to deepen concepts later, but after investigating it did not end up forming a precise answer to that question, could someone explain me a solution or an example to this?

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

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

发布评论

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

评论(2

仙女 2025-01-16 14:49:44

并行继承层次结构产生了许多不必要的类,并使代码非常脆弱且紧密耦合。
例如,我们有类 Sportsman 及其 Goal

public abstract class Sportsman
{
    public string Name { get; set; }

    public abstract string ShowGoal();
}

和具体类 Footballer:

public class Footballer : Sportsman
{
    public override string ShowGoal()
    {
        return new FootballerGoal().Get();
    }
}

Runner:

public class Runner : Sportsman
{
    public override string ShowGoal()
    {
        return new RunnerGoal().Get();
    }
}

那么我们就有了他们的目标:

public abstract class Goal
{
    public abstract string Get();
}

及其具体类:

public class FootballerGoal : Goal
{
    public override string Get()
    {
        return "Score 1 goal";
    }
}

和跑步者目标:

 public class RunnerGoal : Goal
{
    public override string Get()
    {
        return "Run 1 km";
    }
}

现在,可以看出,如果我们添加新类型运动员,那么我们需要在Goal的层次结构中添加一个新类。

我们可以尝试通过使用依赖注入和提取接口方法来避免创建层次结构树。

首先,我们创建接口:

public interface IGoal
{
    string Visit(Sportsman sportsman);
}

然后实现它:

public class FootballerGoal : IGoal
{
    public string Visit(Sportsman sportsman)
    {
        return "Score 1 goal";
    }
}

并在 Footballer 类中使用它:

public class Footballer : Sportsman
{
    public string ShowGoal(IGoal goal) 
    {
        return goal.Visit(this);
    }
}

现在我们没有层次结构树,我们可以这样调用它:

new Footballer().GetGoal(new FootballerGoal())

更新:

有一篇关于并行继承的好文章层次结构。。它提出了一些解决此任务的方法。让我展示第三种方法。

解决方案 3 折叠层次结构。

优点:

  • 仅维护一个层次结构

  • 易于维护

缺点

  • 经常违反建议零售价。

所以 Footballer 类会像这样:

public class Footballer : Sportsman
{
    public override string ShowGoal()
    {
        return new FootballerGoal().Get();
    }
    
    public string GetGoal()
    {
        return "Score 1 goal";
    }
}

Runner 类会像这样:

public class Runner : Sportsman
{
    public override string ShowGoal()
    {
        return new RunnerGoal().Get();
    }

    public string GetGoal()
    {
        return "Run 1 km";
    }
}

Parallel Inheritance Hierarchies makes many unnecessary classes and makes code very fragile and tightly coupled.
For example, we have class Sportsman and its Goal's.

public abstract class Sportsman
{
    public string Name { get; set; }

    public abstract string ShowGoal();
}

and concrete class Footballer:

public class Footballer : Sportsman
{
    public override string ShowGoal()
    {
        return new FootballerGoal().Get();
    }
}

and Runner:

public class Runner : Sportsman
{
    public override string ShowGoal()
    {
        return new RunnerGoal().Get();
    }
}

Then we have their goals:

public abstract class Goal
{
    public abstract string Get();
}

and its concrete classes:

public class FootballerGoal : Goal
{
    public override string Get()
    {
        return "Score 1 goal";
    }
}

And runner goal:

 public class RunnerGoal : Goal
{
    public override string Get()
    {
        return "Run 1 km";
    }
}

Now, it can be seen that if we add new type of sportsman, then we need add a new class to hierarchy of Goal.

We can try to avoid of creation of that hierarchy tree by using dependency injection and extracting method to interface.

At first, we create interface:

public interface IGoal
{
    string Visit(Sportsman sportsman);
}

and then just implement it:

public class FootballerGoal : IGoal
{
    public string Visit(Sportsman sportsman)
    {
        return "Score 1 goal";
    }
}

and use it in Footballer class:

public class Footballer : Sportsman
{
    public string ShowGoal(IGoal goal) 
    {
        return goal.Visit(this);
    }
}

Now we do not have hierarchy tree and we can call it like this:

new Footballer().GetGoal(new FootballerGoal())

UPDATE:

There is a good article about Parallel Inheritance Hierarchies.. It proposes some ways to solve this task. Let me show the third way.

Solution 3 Collapse a hierarchy.

Pros:

  • Only maintain One hierarchy

  • Easy to maintain

Cons

  • Breaks SRP fairly often.

So Footballer class would like this:

public class Footballer : Sportsman
{
    public override string ShowGoal()
    {
        return new FootballerGoal().Get();
    }
    
    public string GetGoal()
    {
        return "Score 1 goal";
    }
}

And Runner class would like this:

public class Runner : Sportsman
{
    public override string ShowGoal()
    {
        return new RunnerGoal().Get();
    }

    public string GetGoal()
    {
        return "Run 1 km";
    }
}
最单纯的乌龟 2025-01-16 14:49:44

c2 wiki 有一个关于并行继承层次结构的页面,其中 ChaoKuoLin 列出了四个可能的解决方案。我在这里对它们进行了解释,并为每个内容提供了一些背景信息。请参阅原始页面以获取完整的说明,包括优点、缺点和示例。

  1. 保持平行的层次结构。
    • 当层次结构具有单独的职责并且每个层次结构都包含许多方法时。
    • 当需要最大灵活性时。
  2. 保留一个层次结构并将另一个折叠到一个类中。
    • 当其中一个层次结构可以简化为单个类时,例如通过将某些方法移动到另一个层次结构。
    • 当其中一个层次结构包含很少的方法时。
  3. 将两个层次结构合二为一。
    • 当层次结构具有相似的职责并且每个层次结构都包含很少的方法时。
  4. 保持部分并行层次结构,其余部分折叠。
    • 当您想要在之前的解决方案中找到中间立场时。

wiki 中建议的另一个解决方案是 Mix In 并且在 如何解决UI案例中的并行继承

The c2 wiki has a page on parallel inheritance hierarchies where ChaoKuoLin lists four possible solutions. I paraphrase them here, along with some context for each. See the original page for a full explanation including advantages, disadvantages, and examples.

  1. Keep the parallel hierarchies.
    • When the hierarchies have separate responsibilities and each contains many methods.
    • When maximum flexibility is required.
  2. Keep one of the hierarchies and collapse the other into a class.
    • When one of the hierarchies can be reduced to a single class, for example by moving some methods to the other hierarchy.
    • When one of the hierarchies contains few methods.
  3. Collapse the two hierarchies into one.
    • When the hierarchies have similar responsibilities and each contains few methods.
  4. Keep a partial parallel hierarchy with the rest collapsed.
    • When you want a middle ground among the previous solutions.

Another solution suggested in the wiki is Mix In and it is also suggested in How to solve parallel Inheritance in UI case?

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