投到一个抽象的课......这怎么可能?

时间:2012-01-02 00:03:41

标签: java inheritance abstract-class

我实际上正在阅读一本关于java设计模式的书,我是新手:)

http://www.amazon.com/Design-Patterns-Java-TM-Software/dp/0321333020/在关于复合模式的章节中,我遇到了一个令我困惑的代码,一个抽象类的抽象,我也不太清楚当sub-clase调用抽象超类的构造函数时会发生什么, 你能帮我吗 !!

我正在谈论的演员是在isTree(Set visited)

        MachineComponent c = (MachineComponent) i.next();
        if (visited.contains(c) || !c.isTree(visited)) 

如何在转换为抽象超类之后调用子类的isTree方法 而isTree超类方法是抽象的吗?

以下是两个类的片段:

package com.oozinoz.machine;
/*
 * Copyright (c) 2001, 2005. Steven J. Metsker.
 */

import java.util.*;
import com.oozinoz.iterator.ComponentIterator;

/**
 * Objects of this class represent either individual machines or composites of
 * machines.
 */

public abstract class MachineComponent {

    /*
     * Subclasses implement this to support the isTree() algorithm.
     */

    protected abstract boolean isTree(Set s);

    // rest of class omitted
}

2:

package com.oozinoz.machine;    
/*
 * Copyright (c) 2001, 2005. Steven J. Metsker.
 */

import java.util.*;
import com.oozinoz.iterator.ComponentIterator;
import com.oozinoz.iterator.CompositeIterator;

 /**
 * Represent a collection of machines: a manufacturing line, a bay, or a
 * factory.
 */

public class MachineComposite extends MachineComponent {
    protected List components = new ArrayList();

    /**
     * @param visited a set of visited nodes
     * @return true if this composite is a tree
     * @see MachineComponent#isTree()
     */

    protected boolean isTree(Set visited) {
        visited.add(this);
        Iterator i = components.iterator();
        while (i.hasNext()) {
            MachineComponent c = (MachineComponent) i.next();
            if (visited.contains(c) || !c.isTree(visited)) 
                return false;
        }
        return true;
    }

    // rest of class omitted
}

5 个答案:

答案 0 :(得分:9)

这是运行时类型(实际类型)和编译时类型之间的区别。

抽象类MachineComponent的类型转换很好,因为实际的对象实例实际上是MachineComponent的一些非抽象子类,它实现了所有的抽象方法。

抽象MachineComponent类是指定变量的编译时类型。但是没有用该抽象类创建(或可以)创建实际实例。

答案 1 :(得分:4)

isTree只是抽象类的抽象。一旦将类初始化为非抽象类,将其转换为抽象将不会改变其内存。因此,在抽象类上调用该方法可以在具体实现上有效地调用它。

它有用的原因是通过抽象实现传递子类。

假设String类有'length'方法。没有必要为每个可能的String类型子类都有一个函数。相反,你转换为具有'length'实现的基本(抽象)String,并传递它。

答案 2 :(得分:3)

好的 - 让我们再试一次:

  

问:你可以演绎抽象课吗?

答:当然 - 你当然可以

例如:

public class UseAbstract
{
  public static void main (String[] args)
  {
    // Instantiate an abstract class
    AbstractPet myDog = new Dog ();
    myDog.sound ();

    // Instantiate a concrete class
    Cat myCat = new Cat ();
    myCat.sound ();

    // Cast a concrete class to an abstract class
    AbstractPet somePet = (AbstractPet)myCat;
    somePet.sound ();
  }
}

abstract class AbstractPet
{
  void sound ()
  {
    System.out.println ("eek");
  }
}

class Dog extends AbstractPet
{
  void sound ()
  {
    System.out.println ("Woof");
  }
}

class Cat extends AbstractPet
{
  void sound ()
  {
    System.out.println ("meow");
  }
}

答案 3 :(得分:2)

好吧,让我们把Cat作为抽象类Animal的子类。

您可以将Cat投射到Animal因为猫是动物。它完成了普通动物所做的一切,因为它具有动物的功能。

对抽象类进行子类化是相同的。您可以简单地使用“is a”,因为它是一个子类。

您可以将动物列表定义为动物园,但它可以有狗和猫 - 毕竟,它们都是动物。

Cat投放到Animal实际上并不比它更少Cat - 您只需告诉您的代码就像对待任何其他动物一样对待它

修改
如果您不喜欢猫(我也不喜欢),让我将您重定向到Wikipedia article about inheritance。如果你不能投射它们,那么抽象类将毫无用处。

答案 4 :(得分:1)

问:你可以演绎抽象课吗?

答:当然 - 你当然可以。

无法做的是调用抽象类的抽象方法。 (从注释部分插入-Andrew Barber-下面) - 您实际上是在子类中调用它的具体实现。