繁体   English   中英

抽象 class 中的 Static 方法

[英]Static methods in an abstract class

我想像这样定义一个抽象方法:

public abstract class Saveable {
    public Set<Field> getFieldSet();
    ...
}

无论对象的 state 是什么, getFields()都应始终返回相同的 output。 但是,我不能将其声明为 static 方法,因为我希望它被覆盖。 现在我正在实现一个 class User ,它扩展了Saveable并且它有一些需要字段集的 static 方法。 显然,我无法得到它,因为我没有 object。 关于设计的任何想法,可以让我获得 static 方法中的字段?

一种方法是通过将正确的 object 的实例传递给 static 方法,然后在该 object 上调用getFields来“伪造” this引用。

另一种选择是将字段列表存储在 class 上的 static 字段中。 您重写的getFields()实现可以返回它(或者最好是它的副本),并且您的 static 方法可以直接访问它。

我的偏好是实现后一个选项,因为它不那么笨拙(因为您永远不必新建一个其他无用的 object 来传递给 static 方法。)此外,它还捕获了类的字段不t 依赖于给定的实例。

不幸的是,继承的 class不能覆盖 static 方法,但它可以通过声明具有相同签名的 static 方法来隐藏它。

如果您的最终目的是在Saveable class 中的另一个继承方法中使用GetFields() ,这对您没有帮助,因为它将始终调用Saveable.getFields() ,而不是扩展 ZA2F2ED4F8EBC2CBBDDZC21 中的 static 方法。

您可以在 Savable 中将当前方法保留为非静态和抽象,并从非静态实现中返回 static Set。

public class User extends Savable {

    public static Set<AField> aSet = new HashSet<AField>();

    @Override
    public Set<? extends Field> getFields() {
        return aSet;
    }
}

调用 static 方法时,您将类的名称称为 scope。

所以实际上没有覆盖的意义,你只是在隐藏它。

此外,由于同样的原因,它不能被继承,因为它属于 class 类型,而不是 class 实例。

最好的办法是在派生的 class 中调用基类的 static 方法,并具有相同的方法名称。

扩展@dlev 的答案,如何将字段存储在由每个 class 的唯一标识符键控的 hashmap 中。

如果您使用的是 Spring,则可以在每个 object 中注入一组字段。 因此,只有引用将被复制。

这是建议,我制定了。 但是您必须以某种方式命名派生的 class 名称,在加载这些字段时,除了声明方法 static 之外,别无他法。

public abstract class Saveable {
    public static Set<? extends Field> getFields(Class<? extends Saveable> clazz) {
        return FieldsProvider.get(clazz);
    }
}

public class FieldsProvider {
    private static final Map<Class<? extends Saveable>, Set<? extends Field>> map =
        new HashMap<Class<? extends Saveable>, Set<? extends Field>>();

public static void registerFields(Class<? extends Saveable> clazz, Collection<? extends Field> col) {
    Set<? extends Saveable> set = new HashSet<? extends Saveable>();
    set.addAll(col);
    map.put(clazz, set);
}

public static Set<? extends Field> getFieldSet(Class<? extends Saveable> clazz) {
    Set<? extends Field> set = map.get(clazz);
    if (set != null) {
        return set;
    }
    return Collections.emptySet();
}
}

public class User extends Saveable {
static {
    FieldsProvider.registerFields(User.class, new HashSet<? extends Field>... ;
}

static void someMethod() {
    Set<? extends Field> fieldsSet = getFields(User.class);
    ...
}
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM