我实际上正在阅读一本关于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
}
答案 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-下面) - 您实际上是在子类中调用它的具体实现。