首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在本例中解决代码复制,其中我引入了继承来实际解决代码重复。

如何在本例中解决代码复制,其中我引入了继承来实际解决代码重复。
EN

Stack Overflow用户
提问于 2018-11-16 13:07:59
回答 3查看 78关注 0票数 0

假设我有一个具有不同Scenes的应用程序。每个场景都有一个由多个ScreenElement组成的布局,例如,将绘制到Canvas的矩形框。对于某些Scenes,将使用相同的框。因此,鉴于干燥,我想使用继承。

我想要做的是将ScreenElement存储在一个HashMap (或者最终是一个EnumMap)中,这样我就可以在代码的其他地方调用ScreenElement来更改它们的属性。

这是我现在想出来的..。

以下是基本布局:

代码语言:javascript
复制
Public class BasicLayout {
    private HashMap<String, ScreenElement> screenElements;

    public BasicLayout() {
        screenElements = new HashMap<>();
        screenElements.put("BACKGROUND", new ScreenElement(...));
        screenElements.put("BOXONE", new ScreenElement(...));
        screenElements.put("BOXTWO", new ScreenElement(...));
    }

    public HashMap<String, ScreenElement> getScreenElements() {
        return screenElements;
    }

    public ScreenElement getScreenElement(String elementName) {
        return screenElements.get(elementName);
    }

    public void draw(Canvas canvas) {
        for (ScreenElement screenElement: screenElements) {
            screenElement.draw(canvas);
        }
    }
}

那么另一个布局可能是这样的:

代码语言:javascript
复制
Public class OtherLayout extends BasicLayout {      
    private HashMap<String, ScreenElement> screenElements;

    public OtherLayout() {
        screenElements = new HashMap<>(super.getScreenElements);
        screenElements.put("BOXTHREE", new ScreenElement(...));
        screenElements.put("BOXFOUR", new ScreenElement(...));
    }

    @Override
    public HashMap<String, ScreenElement> getScreenElements() {
        return screenElements;
    }

    @Override
    public ScreenElement getScreenElement(String elementName) {
        return screenElements.get(elementName);
    }

    @Override
    public void draw(Canvas canvas) {
        for (ScreenElement screenElement: screenElements) {
            screenElement.draw(canvas);
        }
}

问题是,通过解决代码复制(我不再需要在我的OtherLayout**),中添加背景、BOXONE和BOXTWO ),我引入了代码复制!**

现在我需要复制getScreenElementsgetScreenElementdraw方法。在这种情况下,您需要重写它们,因为如果没有,getScreenElements总是返回背景、BOXONE和BOXTWO,即使在实际需要背景、BOXONE、BOXTWO、BOXTHREE和BOXFOUR (例如在使用“`OtherLayout”的Scene中)。

希望这是合理的,有人有一个巧妙的解决方案!

澄清:

  • 任何时候BasicLayout都应该有背景,BOXONE和BOXTWO
  • 在任何时候OtherLayout都应该有背景,BOXONE,BOXTWO,BOXTHREE和BOXFOUR。
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-11-16 13:21:16

这应该是可行的:

代码语言:javascript
复制
public class BasicLayout {
    protected HashMap<String, ScreenElement> screenElements = new HashMap<>();

    public BasicLayout() 
    {
        screenElements.put("BACKGROUND", new ScreenElement(...));
        screenElements.put("BOXONE", new ScreenElement(...));
        screenElements.put("BOXTWO", new ScreenElement(...));
    }

    public HashMap<String, ScreenElement> getScreenElements() {
        return screenElements;
    }

    public ScreenElement getScreenElement(String elementName) {
        return screenElements.get(elementName);
    }

    public void draw(Canvas canvas) {
        for (ScreenElement screenElement: screenElements) {
            screenElement.draw(canvas);
        }
    }
}

public class OtherLayout extends BasicLayout {     
    public OtherLayout() {
        screenElements.put("BOXTHREE", new ScreenElement(...));
        screenElements.put("BOXFOUR", new ScreenElement(...));
    }
}
票数 1
EN

Stack Overflow用户

发布于 2018-11-16 14:00:01

我不认为解决继承问题是避免重复的好选择。您总是违反Liskov替换原则是某种解决方式(在您的情况下,不是这样解决:)。这就导致了更大的问题。

第二点继承应该只用于共享行为,而不是数据。

我认为,就你的情况而言,代表团/组成更适合:

代码语言:javascript
复制
public OtherLayout() {
    screenElements = new HashMap<>();
    screenElements.putAll(new BasicLayout().getScreenElements());
    screenElements.put("BOXTHREE", new ScreenElement());
    screenElements.put("BOXFOUR", new ScreenElement());
}

因为从外观上看,这两个类唯一常见的是源元素映射中的元素。

还有一个更笼统的注解。不要像错误的抽象那样害怕重复。引用现代计算机科学先驱的话(Edsger Dijkstra):

抽象的目的不是含糊不清,而是要创造一个新的语义层次,在这个层次上,我们可以绝对精确。

票数 1
EN

Stack Overflow用户

发布于 2018-11-16 13:35:15

基于示例代码,只需要一个类就可以在构造函数中接受它将负责的元素。例如:

代码语言:javascript
复制
public class Layout {
    private final Map<String, ScreenElement> screenElements;

    public Layout(Map<String, ScreenElement> screenElements) {
        this.screenElements = screenElements;
    }

    // other methods
}

从您的示例来看,代码库中的某个地方将知道如何创建一个BasicLayoutOtherLayout。重构该代码并提取映射,然后传递给构造函数。例如:

代码语言:javascript
复制
 // in some method that knows when to create a `BasicLayout` or `OtherLayout`
 Map<String, ScreenElement> basicScreenElements = new HashMap<>();
 basicScreenElements .put("BACKGROUND", new ScreenElement(...));
 basicScreenElements .put("BOXONE", new ScreenElement(...));
 basicScreenElements .put("BOXTWO", new ScreenElement(...));
 Layout basicLayout = new Layout(basicScreenElements);

// ....
 Map<String, ScreenElement> otherScreenElements = new HashMap<>();
 otherScreenElements .put("BOXTHREE", new ScreenElement(...));
 otherScreenElements .put("BOXFOUR", new ScreenElement(...));
 Layout otherLayout = new Layout(otherScreenElements);
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53338543

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档