【问题标题】:Java Static Method: Create object of current typeJava 静态方法:创建当前类型的对象
【发布时间】:2012-10-27 23:13:00
【问题描述】:

我有一个抽象类类型,我从它继承来创建新类。作为等效示例,请考虑:

public abstract class BaseClass {
    public BaseClass(String input)
    {
        ...
    }
    public abstract void doSomething();
    public String getResult()
    {
        ...
    }
}

现在我可以重写 BaseClass 并实现“doSomething”来执行不同的操作(例如,如果我真的在使用字符串,则反转或大写,虽然我不是真的,这只是一个例子)。

最常见的用法是:

BaseClass bc = new ExtendsBaseClass(input);
bc.doSomething();
String result = bc.getResult()

所以我想为此创建一个静态包装方法。
我想实现:

public static String doSomethingForResult(String input)
{
     BaseClass bc = /*new current type*/;
     bc.doSomething();
     return bc.getResult();
}

但我不知道该用什么替换该评论,或者如何使它起作用;我不想强迫每个实现类重新实现它(如果这在概念上是可能的;因为 abstract static 是不允许的。

【问题讨论】:

  • 你可以有一个单独的工厂类,它可以创建子类的实例。 BaseClass bc = BCFactory.getDefaultInstance();。但是你不应该使用那个静态方法。

标签: java class inheritance static


【解决方案1】:

静态方法不是多态的,因此不能被继承和覆盖。你想做的事是不可能的。

【讨论】:

  • 嗯,它们是继承的。尽管您认为这是不可能的,但您可能是对的。
【解决方案2】:

在这种情况下,您为什么要为静态事物烦恼?

只需从多态中受益并合并doSomething()getResult()

你最终会得到:

public abstract class BaseClass {
    public BaseClass(String input)
    {
        ...
    }
    public abstract String doSomething();
}

你的客户看起来像:

BaseClass bc = new ExtendsBaseClass(input);
String result = bc.doSomething();

一般来说,定义一个单独的 getResult() 方法在特定情况下是有意义的,比如实现 Builder 模式。实际上,有几个不同的方法参与到对象构造中,并最终调用了一种getResult() 方法。

---------在您的评论之后------ ------

如果如您所说,常见情况是使用doSomething() 后跟getResult(),并且根据特定的子类,您可以使用模板方法 模式:

public abstract class BaseClass {
        public BaseClass(String input)
        {
          // assigments
        }

        public String process(){ //process is a template method
         doSomething();
         return getResult();
        }

        protected abstract void doSomething();

        protected abstract String getResult();
}

public class ExtendedClass extends BaseClass {

   protected void doSomething(){
     //...
   }

   protected String getResult(){
     //....
   }
}

您的客户只会调用process() 方法:

BaseClass bc = new ExtendsBaseClass(input);
String result = bc.process();

但是请 :),尽可能避免静态的东西,它们不会导致良好的 OO 编程。

【讨论】:

  • 我想我可能过度简化了我的例子。实际上,我使用的是位图而不是字符串。我将位图作为输入,但将其存储和处理为 2D 颜色数组。然后我的结果方法将其重新组合为位图。但我不确定我是否总是想把它重新组合在一起,我可能想将原始处理后的数组传递给另一个方法。
【解决方案3】:

所以我想为此创建一个静态包装方法。

我想我明白你为什么要这样做了。您需要一种简单的方法来执行一组常见的操作,而无需一次又一次地复制样板代码。但正如您现在痛苦地意识到的那样,静态方法在继承层次结构中没有位置。我建议您从各种 Apache Commons 项目及其 XxxUtils 类中获得灵感,这些类仅由静态方法组成,完全存在于它们所作用的类的层次结构之外。

考虑Commons IO 中的类FileUtils。这只是静态方法,但它们非常有用。考虑两种方法:

static byte[] readFileToByteArray(File file) // Reads the contents of a file into a byte array.
static String readFileToString(File file) // Reads the contents of a file into a String

一种方法处理文件和字节数组,另一种处理文件和字符串?你怎么知道哪个做什么 - 因为它使用一个描述性的名称来拼写它。没有继承、实现、多态性问题,因为 FileUtils 完全存在于文件、字符串、字节数组等的继承层次结构之外。

让我们回到您假设的方法。我会将这个方法放在一个名为 MyUtils 或 BitmapUtils 的单独类中,并为每个有意义的具体类组合创建一个方法。

public static String doSomethingWithExtendsBaseClass(String input)
{
     BaseClass bc = new ExtendsBaseClass();
     bc.doSomething();
     return bc.getResult();
}

public static String doSomethingWithOtherClass(String input)
{
     BaseClass bc = new OtherClass();
     bc.doSomething();
     return bc.getResult();
}

但我不知道用什么替换该评论,或者如何使它起作用

简单 - 您只需在方法中直接实例化具体类,并使用相应的名称。

【讨论】:

    【解决方案4】:

    我认为您可以在 BaseClass 中定义一个静态方法,然后使用 BaseClass 作为参数类将另一个类作为参数传递给它,例如

    public static String doSomethingForResult(String input ,BaseClass bc){
        bc.doSomething();
        return bc.getResult();
    }
    

    那么在你的ExtendedBaseClass你可以写成:

        ExtendedBaseClass extendedBaseObject= new ExtendedBaseClass();
        String result = BaseClass.doSomethingForResult("input", extendedBaseObject);
        System.out.println(result);
    

    【讨论】:

    • @NagetiveVoter:请发表评论。
    • 在这里,您除了使用静态方法重新实现模板方法概念外,什么都不做。但是,doSomethingForResult 永远不会被覆盖,因为静态方法不会导致 OO 反模式。
    • @Mik378:我认为 OP 想要作为包装静态方法:“So I want to make a static wrapper method for this.”。在doSomethingForResult 中调用的方法,即doSomethinggetResult 是完全可覆盖的真正方法。
    • 我同意这就是他的要求:静态包装器。但他的问题听起来确实像是需要建议而不是确定性。当您在基类中创建此静态方法时,您正在手动完成 Java 运行时 => 通过基类访问子类中的覆盖方法的工作。为什么不简单地将多态性与模板方法(非静态)一起使用,就像我在回答中所写的那样。此外,初看时静态类的签名往往不清楚。
    • @Mik378:原始方法中使用了多态性。我回答了我认为的问题。我了解您的意见,并且确实看到了您的详细答案。这是看待问题的不同方面。谢谢!!
    猜你喜欢
    • 2015-06-26
    • 1970-01-01
    • 2015-04-28
    • 1970-01-01
    • 1970-01-01
    • 2018-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多