继承尽管作文?

时间:2010-11-04 02:37:16

标签: java

我通过Java World中的文章做了一些关于作文的阅读:http://www.javaworld.com/javaworld/jw-11-1998/jw-11-techniques.html?page=1

在该文章中,它指导了如何在不使用extends关键字的情况下进行继承。我这样做。这可以吗?它似乎对我有用。

以下是代码:

继承代码示例:文章的第2页。 根据这篇文章,它运作良好:

class Fruit {
    public int peel() {

            System.out.println("Peeling is appealing.");
            return 1;
        }
    }

class Apple extends Fruit {
}

class Example1 {

    public static void main(String[] args) {

        Apple apple = new Apple();
        int pieces = apple.peel();
    }
}

修改后,它不再适用:

class Peel {

    private int peelCount;

    public Peel(int peelCount) {
        this.peelCount = peelCount;
    }

    public int getPeelCount() {

        return peelCount;
    }
}

class Fruit {

// Return a Peel object that
// results from the peeling activity.
    public Peel peel() {

        System.out.println("Peeling is appealing.");
        return new Peel(1);
    }
}

// Apple still compiles and works fine
class Apple extends Fruit {
}

// This old implementation of Example1
// is broken and won't compile.
class Example1 {

    public static void main(String[] args) {

        Apple apple = new Apple();
        int pieces = apple.peel();
    }
}

现在通过合成重用:

class Fruit {

// Return int number of pieces of peel that
// resulted from the peeling activity.
public int peel() {

System.out.println("Peeling is appealing.");
        return 1;
    }
}

class Apple {

    private Fruit fruit = new Fruit();

    public int peel() {
        return fruit.peel();
    }
}

class Example2 {

    public static void main(String[] args) {

        Apple apple = new Apple();
        int pieces = apple.peel();
    }
}

后来的变化:

class Peel {

    private int peelCount;

    public Peel(int peelCount) {
        this.peelCount = peelCount;
    }

    public int getPeelCount() {

        return peelCount;
    }
}


class Fruit {

// Return int number of pieces of peel that
// resulted from the peeling activity.
public Peel peel() {

System.out.println("Peeling is appealing.");
        return new Peel(1);
    }
}

// Apple must be changed to accomodate
// the change to Fruit
class Apple {

    private Fruit fruit = new Fruit();

    public int peel() {

        Peel peel = fruit.peel();
        return peel.getPeelCount();
    }
}

// This old implementation of Example2
// still works fine.
class Example1 {

    public static void main(String[] args) {

        Apple apple = new Apple();
        int pieces = apple.peel();
    }
}

稍后它可以通过接口执行polymorph:请参阅Javaworld第4页上的“使用接口设计”。我无法在此处发布其他链接。

interface Peelable {

int peel();
}

class Fruit {

// Return int number of pieces of peel that
// resulted from the peeling activity.
public int peel() {

System.out.println("Peeling is appealing.");
            return 1;
        }
    }

    class Apple implements Peelable {

        private Fruit fruit = new Fruit();

        public int peel() {
            return fruit.peel();
        }
    }

    class FoodProcessor {

        static void peelAnItem(Peelable item) {
            item.peel();
        }
    }

    class Example5 {

        public static void main(String[] args) {

            Apple apple = new Apple();
            FoodProcessor.peelAnItem(apple);
        }
    }

密钥不是继承,而是创建超类的新实例。而不是传统的多态性。据说使用这种方法比继承更好,因为继承被破坏了。

编辑:稍后,如果我们希望水果变成不同类型而不是Apple,我们可以这样做:

class Banana implements Peelable {

    private Fruit fruit = new Fruit();

    public int peel() {
        return fruit.peel();
    }
}

这是多态性如何通过组合完成的。因此,如果一个方法需要一个可以剥离的水果,我们只需要将Peelable对象传递给它而不是水果。

请阅读第3个答案。我为这个主题添加了更多信息。

3 个答案:

答案 0 :(得分:4)

如果你要征求意见,我就要说:

通过组合进行的继承不一定更好,也不一定比通过extends的严格继承更糟糕。它们完全用于不同的目的。

组合的一个好处是它允许在API中使用更有限的一组潜在操作 - 例如,可以定义一个Stack类来继承LinkedList,但添加一个{{ 1}}和push()方法。但是,没有办法通过调用pop()add(elem, 4)之类的东西来阻止客户端代码滥用堆栈,从而绕过堆栈。作文解决了这个问题。

然而,扩展课程也有其好处。例如,假设你要制作一个get(5),但你不想要任何整数&lt; 0.如果您在Stack<Integer>中包含Stack,那么您必须包含方法GreaterThanZeroStackpush()pop()以及其他任何方法是正确操作所必需的。这会产生许多不必要的样板重复代码。如果您向堆栈添加另一个方法(如peek()),它还会创建不必要的维护。如果您扩展punch(),则只需覆盖一个方法 - Stack。此外,您现在可以将其声明为add(Integer i),或将其传递给接受参数Stack<Integer> s = new GreaterThanZeroStack()的方法。你可以用作文来做这件事吗?没机会。

组合和扩展有两个完全不同的目的,组合的继承不一定是要遵循的模式。


你的案例中,按扩展名继承是正确的。苹果是一种水果。苹果不含水果。如果您要向Fruit添加另一种方法,例如Stack s,那么Apple会免费获得该方法,而对于组合,Apple必须重新实现该方法,如下所示:

public int weight() {
    return fruit.weight();
}

然后每次更改重量时都会更改,例如返回类型或名称。

答案 1 :(得分:1)

一个重要的考虑因素是,通过构图,你会失去“is-a”关系。复合水果的苹果不是水果,不能传递给需要水果的方法。

并不是说继承被破坏了,只是它被过度使用和误用了。

关于使用多态接口的评论中的要点很好。如果您完全可以控制,则可以使用界面和组合构建整个系统。你可能最应该 - “更喜欢构图而不是继承”。

但是,它“更喜欢......结束”,而不是“替换......”。在某些情况下,某些东西的合理公共接口太大而无法为所有内容编写传递包装方法。我可以想到我编写的一个GUI工具包,它有6个代表GUI系统核心部分的顶级抽象类 - 它们绝对是使用继承而不是接口正确设计的。基本组件具有大约120种方法的大型公共接口。我肯定不会想要一个接口,然后在每个单独的具体组件中实现120个包装器方法。

答案 2 :(得分:0)

请查看这篇文章:http://www.javaworld.com/javaworld/jw-12-1998/jw-12-techniques.html

在第2页中,有一个示例解释了您无法从Java中的多个父级继承的钻石问题。

在文章中,作者通过接口介绍了Java中的多重继承。

基于此,以下是我提出的Java中的多重继承的样子:

interface Animal{
    public void getLegs();
}

class Dinosour implements Animal{
    int legs=4;
    public int getLegs(){
        return this.legs;
    }
}

class Frogs implements Animal{
    int legs=2;
    public int getLegs(){
        return this.legs;
    }
}

class Frogosour implements Animal {
    Dinosour father = new Dinosour();
    Frog mother = new Frog();
    int legs;
    public int getLegs(){
        return (father.getLegs()+mother.getLegs())/2;
    }
}

这是多重继承的想法,我可以在阅读完文章后提出来。你怎么看?

我在问,因为当我第一次学习编程时,它总是通过扩展来继承。现在,正如我所听到的,我的同学们说赞成作文,即使在继承的情况下,也比使用扩展的继承概念更好。因此,组合应该优于继承,另一个原因是它接近函数式编程。我只想听到不同意见。