要求子类实现一个静态方法

huangapple go评论89阅读模式
英文:

Require subclass to implement a static method

问题

Coming from Python and Objective-C land, I may not fully understand what static methods are in Java, I think of them as "methods that operate on all members of the class" or "class-specific methods that are available when you don't have an instance of that class."

But is there a syntax for saying: "This abstract superclass requires each concrete subclass to implement this static method"? I know that static abstract isn't permitted, but it would conceptually be something like this:

public abstract class Lander {

    @RequireImplmentationInSubclass     // clearly my made-up name...
    static abstract boolean probe(Radio radio);
}

public class MarsLander extends Lander {
    static boolean probe(Radio radio) {
        // ... some MarsLander specific implementation
    }
}

public class LunarLander extends Lander {
    static boolean probe(Radio radio) {
        // ... some LunarLander specific implementation
    }
}

update

... and somewhere else, a factory method does something like:

if (MarsLander.probe(radio)) {
    ... create an instance of MarsLander and work with it
} else if (LunarLander.probe(radio)) {
    ... create an instance of LunarLander and work with it
}

In my application, creating an instance invokes a lot of machinery, so I need to call probe() on a class method before I create an instance of the class.

I looked over https://stackoverflow.com/questions/2689312/is-there-a-way-to-make-sure-classes-implementing-an-interface-implement-static-m, and most of the responses were "why would you want to do that?".

I hope this example makes it clearer. Perhaps there's a more Java-esque way to remind the developer that a class-visible probe() method is required?

英文:

Coming from Python and Objective-C land, I may not fully understand what static methods are in Java, I think of them as "methods that operate on all members of the class" or "class-specific methods that are available when you don't have an instance of that class."

But is there a syntax for saying: "This abstract superclass requires each concrete subclass to implement this static method"? I know that static abstract isn't permitted, but it would conceptually be something like this:

public abstract class Lander {

    @RequireImplmentationInSubclass     // clearly my made-up name...
    static abstract boolean probe(Radio radio);
}

public class MarsLander extends Lander {
    static boolean probe(Radio radio) {
        // ... some MarsLander specific implementation
    }
}

public class LunarLander extends Lander {
    static boolean probe(Radio radio) {
        // ... some LunarLander specific implementation
    }
}

update

... and somewhere else, a factory method does something like:

if (MarsLander.probe(radio)) {
    ... create an instance of MarsLander and work with it
} else if (LunarLander.probe(radio)) {
    ... create an instance of LunarLander and work with it
}

In my application, creating an instance invokes a lot of machinery, so I need to call probe() on a class method before I create an instance of the class.

I looked over https://stackoverflow.com/questions/2689312/is-there-a-way-to-make-sure-classes-implementing-an-interface-implement-static-m and most of the responses were "why would you want to do that?".

I hope this example makes it clear(er). Perhaps there's' a more Java-esque way to remind the developer that a class-visible probe() method is required?

答案1

得分: 1

以下是您提供的代码的翻译:

"没有办法要求一个静态方法。

但您可以创建一个具有非静态方法的工厂类:

public abstract class LanderFactory<L extends Lander> {
public abstract L createLander();
public abstract boolean probe(Radio radio);
}

您甚至可以拥有一个LanderFactory实现的注册表,以便它们有效地充当单例:

public abstract class LanderFactory<L extends Lander> {
private static final Map<Class<? extends Lander>,
LanderFactory<? extends Lander>> registry
= Map.of(MarsLander.class, new MarsLanderFactory(),
LunarLander.class, new LunarLanderFactory());

public static LanderFactory&lt;? extends Lander&gt; getInstance(
                                            Class&lt;? extends Lander&gt; type) {
    LanderFactory&lt;? extends Lander&gt; factory = registry.get(type);
    if (factory == null) {
        throw new IllegalArgumentException(&quot;没有已知的工厂用于 &quot; + type);
    }
    return factory;
}

public abstract L createLander();

public abstract boolean probe(Radio radio);

}

public class MarsLanderFactory extends LanderFactory<MarsLander> {
@Override
public MarsLander createLander() {
return new MarsLander();
}

@Override
public boolean probe(Radio radio) {
    // ...
}

}

public class LunarLanderFactory extends LanderFactory<LunarLander> {
@Override
public LunarLander createLander() {
return new LunarLander();
}

@Override
public boolean probe(Radio radio) {
    // ...
}

}"

英文:

There is no way to require a static method.

But you can create a factory class with non-static methods:

public abstract class LanderFactory&lt;L extends Lander&gt; {
    public abstract L createLander();
    public abstract boolean probe(Radio radio);
}

You can even have a registry of LanderFactory implementations, so they effectively act as singletons:

public abstract class LanderFactory&lt;L extends Lander&gt; {
    private static final Map&lt;Class&lt;? extends Lander&gt;,
                             LanderFactory&lt;? extends Lander&gt;&gt; registry
        = Map.of(MarsLander.class, new MarsLanderFactory(),
                 LunarLander.class, new LunarLanderFactory());

    public static LanderFactory&lt;? extends Lander&gt; getInstance(
                                                Class&lt;? extends Lander&gt; type) {
        LanderFactory&lt;? extends Lander&gt; factory = registry.get(type);
        if (factory == null) {
            throw new IllegalArgumentException(&quot;No factory known for &quot; + type);
        }
        return factory;
    }

    public abstract L createLander();

    public abstract boolean probe(Radio radio);
}

public class MarsLanderFactory extends LanderFactory&lt;MarsLander&gt; {
    @Override
    public MarsLander createLander() {
        return new MarsLander();
    }

    @Override
    public boolean probe(Radio radio) {
        // ...
    }
}

public class LunarLanderFactory extends LanderFactory&lt;LunarLander&gt; {
    @Override
    public LunarLander createLander() {
        return new LunarLander();
    }

    @Override
    public boolean probe(Radio radio) {
        // ...
    }
}

答案2

得分: 0

I tried your code(and other things surrounding this), and I'd like to tell you there's a way but I don't think there is.

我尝试了你的代码(以及与此相关的其他事情),我想告诉你有一种方法,但我认为没有。

I would instead recommend using a utility class that supports this static functionality you're looking for. For example, a LanderUtility class that has static methods in it might solve this in a reasonable way.

我建议使用支持你所寻找的静态功能的实用类。例如,一个具有静态方法的 LanderUtility 类可能以合理的方式解决这个问题。

Mostly though, I don't think of using static methods in that way in Java. The real power in what is going on with this abstract class is that you can count on (somewhat) a certain type of behavior from a child. Notably, for this to matter, the child needs to be instantiated in the first place, and you can use a normal, non-static method and have the child implement that instead.

但总的来说,我认为在Java中不应该以这种方式使用静态方法。这个抽象类的真正强大之处在于你可以(在某种程度上)依赖于子类的某种行为。值得注意的是,为了让这个有意义,子类需要首先被实例化,并且你可以使用普通的非静态方法,让子类来实现它。

英文:

I tried your code(and other things surrounding this), and I'd like to tell you there's a way but I don't think there is.

I would instead recommend using a utility class that supports this static functionality you're looking for.For example, a LanderUtility class that has static methods in it might solve this in a reasonable way.

Mostly though, I don't think of using static methods in that way in Java. The real power in what is going on with this abstract class is that you can count on(somewhat) a certain type of behavior from a child. Notably, for this to matter, the child needs to be instantiated in the first place and you can use a normal, non-static method and have the child implement that instead.

答案3

得分: 0

"methods that operate on all members of the class"
这是不正确的。static 方法不操作类的任何成员。
static 上下文中禁止使用 this

我觉得你的问题本身已经包含了你要找的答案。static abstract 之所以不存在,是因为一方面你希望它根据是 LunarProbe 还是 MarsProbe 行为不同,另一方面你希望它独立于 LunarProbeMarsProbe 的实例。static abstract 自相矛盾。

此外

static boolean probe() {
     // ... 一些 MarsLander 特定的实现
     // 这里应该放什么?你无法访问这个类的任何实例。
}

static abstract 违反了面向对象编程的一个原则,叫做多态性

英文:
&quot;methods that operate on all members of the class&quot;

This is not right. static methods operate on no members of a class.
Use of this is prohibited in static contexts.

I feel your question itself has the answer you are looking for. static abstract doesnt exists because on one hand you want it to behave differently (based on if it is a LunarProbe or a MarsProbe) and on the other hand you want it to be independent of the instance of LunarProbe and MarsProbe. static abstract contradicts itself.

Besides

static boolean probe() {
     // ... some MarsLander specific implementation
     // what goes here? you dont have access to any instance of this class.
}

static abstract violates a tenet of OOP called polymorphism.

答案4

得分: 0

在Java中,可以直接在类引用上调用静态方法。无论是抽象类还是普通类都可以。

因此,静态和抽象修饰符不能一起使用。否则,如果lander方法未实现,这段代码的输出将是什么呢?这就是为什么它是非法的。

Lander.probe();

但是,我认为我们可以从超类的静态方法中抛出一个异常,并在异常消息中提供一些提示。我们可以强制实现静态方法。

public abstract class Lander {
  static boolean probe() {
    throw new RuntimeException("哎呀!!!我为什么会在这里?");
  }
}

public class MarsLander extends Lander {
  static boolean probe() {
    // ... 一些MarsLander特定的实现
  }
}

public class LunarLander extends Lander {
  static boolean probe() {
    // ... 一些LunarLander特定的实现
  }
}

这样,如果有一个Lander的实现没有实现静态probe方法,probe方法将被继承,但这将引发运行时异常。

英文:

In Java, static methods is allowed to be invoked directly on class references. It does not matter whether it is a abstract class or a normal class.

Due to this reason, static and abstract modifiers can't be used together. Otherwise, what would be the output of this code if the lander method is not implemented ? That's why it is illegal.

Lander.probe();

But, I think we can throw an exception from our super class static method with some hint in the exception message. We can enforce implementation of the static method.

public abstract class Lander {
  static boolean probe() {
    throw new RuntimeException(&quot;Oh oh !!! Why am I here ??&quot;);
  }
}

public class MarsLander extends Lander {
  static boolean probe() {
    // ... some MarsLander specific implementation
  }
}

public class LunarLander extends Lander {
  static boolean probe() {
    // ... some LunarLander specific implementation&#39;
  }
}

That way, if there is a Lander implementation which has not implemented a static probe method, the probe method will get inherited but this will throw a run time exception.

答案5

得分: 0

方法不能同时是抽象的和静态的,因为抽象方法必须被重写,而在Java中静态方法不能被重写。哪个类实现了静态方法是在编译时确定的。您可以在子类中使用相同签名声明静态方法,但这不被视为重写,因为不会有运行时多态性。父类的静态方法在子类中被“屏蔽”。如果派生类定义了与基类中的静态方法相同签名的静态方法,则派生类中的方法将隐藏基类中的方法。

英文:

Methods can't be both abstract and static, because abstract methods have to be overridden, and static methods in Java cannot be overridden. Which class implementation of a static method is used is determined at compile time. You can declare a static method with the same signature in a subclass, but it is not considered overriding because there won’t be any run-time polymorphism. The static method of the superclass is 'masked' in the subclass. If a derived class defines a static method with the same signature as a static method in the base class, the method in the derived class hides the method in the base class.

huangapple
  • 本文由 发表于 2020年7月30日 03:40:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/63161290.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定