1

有没有一种设计模式,我可以让一个对象具有某种状态,他从一个扩展对象开始,但一段时间后又回到它的超级对象。

例如 - 部分文件继承自文件,完成后它将成为一个文件。

4

4 回答 4

2

不,Java 中没有类型突变(公平地说,我想不出任何现代语言都有它)。

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

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

现在,您需要类型突变吗?如果您只需要处理您的对象,就好像它是其超类的直接实例一样,您已经可以做到了。类型突变的主要区别在于您调用了被覆盖的方法,但如果类型层次结构设计正确,这通常很好。

假设我要设计一个 PartialFile 类(假设名称正确定义了它是什么),而不是使用继承,我会使用 composition :我会创建一个装饰类,其实例将有一个 variable private File sourceFile

于 2012-11-13T12:17:54.960 回答
1

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

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

public class PartialFile extends File{
    // methods
    }

PartialFile partFile = new PartialFile();

// do operations on partFile 

File file = partFile;

// do operations on file

因为PartialFileextends File,你真的不需要“把它变成它的超类”——它已经是超类的一个实例。

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

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

您无需将partFilea 更改为file使用File对象的方法 - 只需直接使用它们,因为 Java VM 知道 aPartialFile也是 a File

您不能真正将子类型更改为它的超类型——Java VM 将始终知道它真正是什么类型——但你可以欺骗它。如果您使用以下代码...

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

File file = partFile;
// do operations on file

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

如果你做这样的事情......

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

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

您可以在方法中创建和使用 a PartialFile,但完成后将其作为简单的File. 从现在开始,每当你引用这个对象时,Java VM 都会假装它是一个File. 但是,从技术上讲,它始终是 a ,并且如果您愿意,PartialFile它不会阻止您将其转换回 a ,就像这样......PartialFile

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

所以这只是一个伪装。

于 2012-11-13T12:18:33.573 回答
0

使用设计模式状态和/或工厂方法。

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

像这样的东西:

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

}
于 2012-11-14T07:33:48.347 回答
0

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

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

PartialFile partialFile;
// Code...
File file = (File) partialFile;
于 2012-11-13T12:18:15.290 回答