【问题标题】:Cast to an abstract class...how this is possible?转换为抽象类……这怎么可能?
【发布时间】:2023-03-18 02:48:01
【问题描述】:

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

http://www.amazon.com/Design-Patterns-Java-TM-Software/dp/0321333020/在关于复合模式的章节我遇到了一个让我困惑的代码,一个抽象类的强制转换,我也不太明白当子类调用抽象超类的构造函数时会发生什么,可以请你帮帮我!

我所说的演员表是在 isTree(已访问的集合)中

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

      

如果isTree 超类方法是抽象的,我们如何在转换为他的抽象超类之后调用子类的isTree 方法?

这里是两个类的sn-ps:

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
}

【问题讨论】:

  • 如果您要转储整个文件,请正确格式化您的代码。

标签: java inheritance abstract-class


【解决方案1】:

问:你能转换成抽象类吗?

A:当然——当然可以。

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

【讨论】:

  • 是的……完全不正确。
  • @mre,这有什么不对?抽象方法没有代码,你会调用什么?
  • 这是真的,虽然我可以看到有些人可能不会这么认为,如果他们对术语的挑剔与回答者不同。如果你认为你在调用抽象函数,你实际上是在子类中调用它的具体实现。
  • @Paul,对我来说,这个答案似乎是说不可能调用抽象类的抽象方法,这根本不是真的。
【解决方案2】:

好吧,让我们以Cat 为例,它是抽象类Animal 的子类。

您可以将Cat 转换为Animal,因为猫是动物。它做正常动物所做的一切,因为它具有动物的功能。

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

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

Cat 转换为Animal 实际上并不会使它比原来的Cat 更小 - 您只需告诉您的代码像对待任何其他动物一样对待它。

编辑
如果您不喜欢猫(我也不喜欢),让我将您重定向到Wikipedia article about inheritance。如果不能强制转换抽象类,它们将毫无用处。

【讨论】:

    【解决方案3】:

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

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

    假设一个 String 类有 'length' 方法。没有必要为每个可能的 String 类型子类都有一个函数。相反,您转换为具有“长度”实现的基本(抽象)字符串,然后将其传递。

    【讨论】:

      【解决方案4】:

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

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

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

      【讨论】:

      • @wrscheider99 - 绝对正确。事实上,这是一个抽象类的定义——它是一个你不能为其创建任何具体实例的类——你必须在 ORDER 中创建一个具体实例的子类。坦率地说,“接口”在 Java 中往往非常有用。但是抽象类在很多情况下都很重要,包括 OP 的例子。
      【解决方案5】:

      好的,我们再试一次:

      问:你能转换成抽象类吗?

      A:当然可以——当然可以

      例如:

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

      【讨论】:

        猜你喜欢
        • 2014-11-12
        • 1970-01-01
        • 1970-01-01
        • 2022-12-14
        • 2015-11-08
        • 2021-09-16
        • 2014-07-12
        • 1970-01-01
        • 2014-02-19
        相关资源
        最近更新 更多