Java 转换为抽象类…这怎么可能?

Java 转换为抽象类…这怎么可能?,java,inheritance,abstract-class,Java,Inheritance,Abstract Class,我实际上正在读一本关于java设计模式的书,我是一个新手:) 在关于复合模式的章节中,我遇到了一个让我困惑的代码,一个对抽象类的转换,我也不太理解子类调用抽象超类的构造函数时会发生什么,你能帮我吗 我所说的演员阵容在iTree中(已访问场景) 在对子类的抽象超类进行转换之后,我们如何调用子类的isTree方法 而isTree超类方法是抽象的 以下是两个类的片段: package com.oozinoz.machine; /* * Copyright (c) 2001, 2005. Steven

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

在关于复合模式的章节中,我遇到了一个让我困惑的代码,一个对抽象类的转换,我也不太理解子类调用抽象超类的构造函数时会发生什么,你能帮我吗

我所说的演员阵容在iTree中(已访问场景)

在对子类的抽象超类进行转换之后,我们如何调用子类的
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:


问:你能转换成一个抽象类吗

当然可以,当然可以


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

好吧,让我们看一下
Cat
,它是抽象类
Animal
的一个子类

你可以将猫投给动物,因为猫是动物。它做正常动物所做的一切,因为它具有动物的功能

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

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

将一只
扔给一只
动物
实际上并不会使它比以前更像一只
——你只需告诉你的代码对待它就像对待任何其他动物一样

编辑

如果你不喜欢猫(我也不喜欢),让我把你引向另一个方向。如果不能强制转换抽象类,那么抽象类将毫无用处。

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

它之所以有用,是因为它通过抽象实现传递子类


假设String类具有“length”方法。没有必要为每个可能的字符串类型子类都提供一个函数。相反,您可以强制转换到具有“length”实现的基本(抽象)字符串,并传递它。

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

对抽象类
MachineComponent
的类型转换是可以的,因为实际的对象实例实际上是实现所有抽象方法的
MachineComponent
的一些非抽象子类

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

好的-让我们再试一次:


问:你能转换成一个抽象类吗

当然可以,当然可以

例如:

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");
  }
}

是的……完全不是真的。@mre,这有什么不对的?一个抽象方法没有代码,所以你会调用什么?这是真的,但我可以看出,如果一些人对术语的挑剔与回答者不同,他们可能不会这么认为。如果你认为你在调用抽象函数,那么你实际上是在子类中调用它的具体实现。@Paul,对我来说,这个答案似乎是说不可能调用抽象类的抽象方法,这一点都不正确。如果要将整个文件转储到中,请正确设置代码格式。@wrscheider99-完全正确。事实上,这就是抽象类的定义——它是一个不能为其创建任何具体实例的类——为了创建具体实例,必须为其创建子类。坦率地说,“接口”在Java中往往非常非常有用。但是抽象类在很多情况下都很重要,包括OP的例子。
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
}
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");
  }
}