如何使扩展对象转向其超级对象

时间:2012-11-13 12:15:11

标签: java design-patterns polymorphism

是否有一种设计模式,我可以使一个对象具有某种状态,在那里他作为一个扩展对象开始,但过了一段时间后又转回到它的超级。

例如 - 部分文件从文件继承,在完成后它将成为文件。

4 个答案:

答案 0 :(得分:2)

Java中没有类型变异(公平地说,我不能想到任何具有它的现代语言)。

你可能会做什么,但显然不完全相同:

  • 使用构造函数将对象作为参数在另一个类中构建一个新对象(就像你可以做new Float(new Double(2));)。请注意,这不会更改初始对象,因此您必须再次分配包含它的变量。
  • 根据type添加enum变量,指示对象的性质。对于大多数用途来说它足够了(并且可以帮助您避免构建繁重的类型层次结构)。

现在,你需要类型变异吗?如果你只需要处理你的对象,就像它是超类的直接实例一样,你就可以做到。与类型变异的主要区别在于您调用重写的方法,但如果类型层次结构设计正确,则通常很好。

假设我设计了一个PartialFile类(假设名称正确定义它是什么),而不是使用继承,我会使用组合:我会创建一个装饰类,其实例将具有变量{{1 }}

答案 1 :(得分:1)

这个问题存在缺陷 - 扩展Object始终是其超类的一个实例。

在您的示例中,以下内容有效...

public class PartialFile extends File{
    // methods
    }

PartialFile partFile = new PartialFile();

// do operations on partFile 

File file = partFile;

// do operations on file

因为PartialFile扩展File,你真的不需要'把它变成超类' - 它已经是超类的一个实例。

您可以将PartialFile对象视为PartialFileFileObject以及其扩展的任何其他类,同时。您不需要在这些不同的类类型之间进行转换 - 只需直接使用它。对于上面的代码,如果你想调用File.rename()方法,以下两个语句都会做同样的事情......

partFile.rename();
file.rename();

您无需将partFile更改为file以使用File对象的方法 - 只需直接使用它们,因为Java VM知道PartialFile 1}}也是File

您无法真正将子类型更改为其超类型 - Java VM将始终知道它的实际类型 - 但您可以欺骗它。如果您使用以下代码......

PartialFile partFile = new PartialFile();
// do operations on partFile 

File file = partFile;
// do operations on file

然后只有每次使用file而不是partFile时,您将无法使用任何PartialFile方法。它有点伪装成PartialFile,但它实际上并不转换它。

如果你这样做......

public File createFile(){
    PartialFile partFile = new PartialFile();
    // operations on partFile
    return partFile;
}

File file = createFile();
// operations on file

您可以在方法中创建并使用PartialFile,但是当您完成后,将其作为简单的File返回。无论何时从现在开始引用此对象,Java VM都会假装它为File。但是,从技术上讲,它始终是PartialFile,并且如果您愿意,它不会阻止您将其重新投射到PartialFile中,就像这样......

PartialFile partFile = (PartialFile)file;
// operations on partFile

所以它只是一种伪装。

答案 2 :(得分:0)

子类已经是它的超类的一个实例,所以你可以把它强制转换为它的超类

class PartialFile extends File {
// Code...
}

PartialFile partialFile;
// Code...
File file = (File) partialFile;

答案 3 :(得分:0)

使用设计模式State和/或Factory方法。

您可能仍需要进行一些重构,因为您很可能需要一个用于超级的接口/抽象基类。

这样的事情:

class MySwitcher implements SuperInterface {

  private final SuperInterface super = new Super();

  private final SuperInterface subclass = new Subclass();

  private SuperInterface current = super; // Start in state "behaves as super"

  // Method from SuperInterface
  public MyResult doAction(final MyData d) {
    final MyResult res = current.doAction(d);
    current = setImplementationBasedOnResOfDoAction(res);
    return res;
  }

}