Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/323.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何定义必须在接口内重写的常量?_Java_Interface_Constants_Java 7 - Fatal编程技术网

Java 如何定义必须在接口内重写的常量?

Java 如何定义必须在接口内重写的常量?,java,interface,constants,java-7,Java,Interface,Constants,Java 7,为了创建玩家可以选择的工具包,我制作了一个界面: public interface Kit {} 我已经为每个套件实现了它: public class Ninja implements Kit {} 现在,我想设置一些与类相关的常量,而不是与实例相关的常量。 我希望这些在接口的所有实现中都是静态的,并且我希望每个实现都覆盖它们 试试#1: 试试#2: 接口不能像类保存字段那样保存数据。如果您不想实例化工具包,那么很可能需要一个抽象类。将它们视为具有一些实现和字段的接口 注意,请阅读进一步说明

为了创建玩家可以选择的工具包,我制作了一个界面:

public interface Kit {}
我已经为每个套件实现了它:

public class Ninja implements Kit {}
现在,我想设置一些与类相关的常量,而不是与实例相关的常量。 我希望这些在接口的所有实现中都是静态的,并且我希望每个实现都覆盖它们

试试#1:

试试#2:


接口不能像类保存字段那样保存数据。如果您不想实例化
工具包
,那么很可能需要一个抽象类。将它们视为具有一些实现和字段的接口

注意,请阅读进一步说明:

因此,您希望在后台有一个抽象类,而不是一个接口。现在看起来怎么样

public abstract class Kit {
    protected final String name = "Foo";

    public String getName () {
        return name;
    }
}
这里有我们的工具包,每个实现
Kit
的类都可以访问
name
字段。如果它应该是一个常数,我可能会建议把它放在大写。最好也使用静态属性。更多的内容可以阅读

为了说明这一点,我从我们的
抽象类工具包
中继承了两个类<代码>忍者和
测试

public class Ninja extends Kit {
}
这个类的目的只是检查
name
是否真的具有
Foo
的值

然后我们也需要实际的测试类

public class Test extends Kit {
    public static void main (String[] args) {
        Test ninja = new Test ();
        System.out.println(ninja.getName());    // foo
        Ninja ninja2 = new Ninja ();
        System.out.println(ninja2.getName());   // foo
    } 
}
它们都是不同的类型,
Test
resp
Ninja
但它们在
name
字段中都有
foo
的值。对于从
Kit
继承的每个类都是如此

如果必须被覆盖是一项要求,那么我建议添加
Kit
构造函数
,以强制用户添加基类中的数据

public abstract class Kit {
    protected String name;

    public Kit (String name) {
        this.name = name;
    }

    public String getName () {
        return name;
    }
}
现在,从
Kit
继承的每个类都必须调用
super(String)
,这意味着将为每个对象设置
name
字段。它可以不同于
A类扩展套件
B类扩展套件
。这就是你要找的吗

如果是这样的话,那么实施
A类
B类
将沿着这些路线进行

class A extends Kit {
    public A (String name) {
        super (name);
    }
}
对于
B
,它将如下所示

class B extends Kit {
    public B (String name) {
        super (name);
    }
}

现在它们是不同的类,可以容纳不同的字段和方法,但是它们都需要设置基类的
名称
字段:
Kit

静态方法不是虚拟的,这意味着您不能在接口上定义抽象静态方法,并期望它在子类级别被重写和调用,如:

// Doesn't even compile!
public interface Kit {
  static String name();
}

public class Ninja implements Kit {
  @Override public static name() { return "Ninja"; }
}
如果需要在给定类的作用域中将值定义为运行时常量(例如,所有Ninja实例都必须返回
“Ninja”
),则可以在类级别使用常规的、非静态的虚拟方法对名称进行硬编码,或者使用类似于注入的友好方法

public class KitTranslator {
  public void translate(Kit kit) {
    // ...
  }
}
然后,您可以确保应用程序中只存在一个
KitTranslator


我强烈反对使用任何涉及
static
的实现,因为它迟早会打乱应用程序的初始化顺序,并且因为
static
字段会在用户空间中无限传播。另外,由于静态在任何级别上都不是虚拟的,因此在需要扩展代码时都会遇到问题。

最简单的方法是要求子类包含某些特定的静态字段

/**
 * subclass MUST define static field "KIT_NAME" !!!!
 */
public interface Kit

---

public class Ninja implements Kit

    public static final String KIT_NAME = "Ninja"
编译器无法强制执行此要求。这是程序员必须遵循的惯例。这不是什么大问题

在运行时,使用反射从子类读取字段


另一种更奇特的方法是使用注释

@KitInfo(name="Ninja")
public class Ninja implements Kit
这比静态字段要好一点。您甚至可以编写一个预处理器来强制执行对Kit的任何子类都必须注释
@KitInfo
。(什么是预处理器无法完成的?:)


现在,为了好玩,让我们用泛型来解决它

public interface Kit<I extends Kit.Info>
{
    public interface Info
    {
        String name();
    }
}

public class Ninja implements Kit<Ninja.Info>
{
    public static class Info implements Kit.Info
    { 
        public String name(){ return "Ninja"; }
    }
}
公共接口套件
{
公共接口信息
{
字符串名();
}
}
公共级忍者装备包
{
公共静态类信息实现了Kit.Info
{ 
公共字符串名称(){return“Ninja”;}
}
}

在运行时,给定Kit的一个子类,我们可以使用反射来获得
I

的具体类型,因此您希望所有类都有一个唯一的名称,但确保所有实现都有
String getName()
方法?对我来说,这听起来更像是一个抽象类而不是一个接口。@Emz你所说的实现是什么意思?当你做
Ninja a=new Ninja();忍者b=新忍者()
是否希望
a
b
具有不同的值?他们的
name
字段,但仍然确保他们有name字段?@Emz否,因为这些字段应该是与类相关的常量,而不是与实例相关的常量。
@KitInfo(name="Ninja")
public class Ninja implements Kit
public interface Kit<I extends Kit.Info>
{
    public interface Info
    {
        String name();
    }
}

public class Ninja implements Kit<Ninja.Info>
{
    public static class Info implements Kit.Info
    { 
        public String name(){ return "Ninja"; }
    }
}