Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/367.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 - Fatal编程技术网

Java 如何从抽象类扩展枚举类?

Java 如何从抽象类扩展枚举类?,java,Java,有这样的东西: public enum Token { FOO("foo", "f"), QUIT("quit", "q"), UNKNOWN("", ""); ... public parse(String s) { for (Token token : values()) { ... return token; } return U

有这样的东西:

public enum Token
{
     FOO("foo", "f"),
     QUIT("quit", "q"),
     UNKNOWN("", "");
     ...

     public parse(String s) {
         for (Token token : values()) {
              ...
              return token;
         }
         return UNKNOWN;
     }
}
抽象类:

abstract class Base 
{
    private boolean run;

    Base() {
        run = true;

        while (run) {
             inp = getInput();
             act(inp);
        }
    }

    public boolean act(String s) {
        boolean OK = true;
        switch (Token.parse(inp)) { /* Enum */
             case FOO:
                    do_foo();
                    break;
             case QUIT:
                    run = false;
                    break;
             case UNKNOWN:
                    print "Unknown" + inp;
                    OK = false;
                    break;
             }
         }
         return OK;
    }
}
和扩展器:

class Major extends Base
{

}
我想要的是扩展
act
,就像
super
无法处理它一样,然后尝试在
Major
中处理它。例如,添加
PRINT\u STAT(“PRINT statistics”、“ps”)
——但同时让
Base
类处理默认值,如
QUIT

这是一个完全错误的方法吗

到目前为止,我所做的是添加一个接口,通常是:

public interface BaseFace
{
      public boolean act_other(String inp);
}
在类
Base中实现BaseFace

      case UNKNOWN:
          OK = act_other(inp);
并且在课堂上主修:

  public boolean act_other(String inp) { 
       if (inp.equals("blah")) {
            do_blah();
            return true; 
       }
       return false;
  }
这看起来像一个可用的设计吗

和,主要问题:

是否有一些好的方法来扩展
令牌
类,这样我就可以在
Major
中使用与
Base
中相同的切换方法?我想知道的是,一个是更好的设计,另一个是我是否必须为
Major
创建一个新的令牌类,或者我是否可以以某种方式扩展或重用现有的令牌类



编辑:概念的要点是拥有
Base
类,我可以轻松地在处理各种类型输入的不同项目中重用该类。

所有枚举隐式扩展枚举。在Java中,一个类最多可以扩展另一个类

但是,您可以让enum类实现接口

发件人:

注意:所有枚举都隐式扩展java.lang.Enum。因为一个类只能扩展一个父类(请参见声明类),所以Java语言不支持状态的多重继承(请参见状态、实现和类型的多重继承),因此枚举不能扩展任何其他内容

为Java 8编辑:

从Java8开始,接口可以包括。这允许您在接口中包含方法实现(而不是状态)。尽管此功能的主要目的是允许公共接口的演化,但您可以使用它来继承一个自定义方法,该方法定义多个枚举类之间的公共行为

然而,这可能是脆弱的。如果以后将具有相同签名的方法添加到类中,它将覆盖默认方法。(当在类的超类和接口中都定义了方法时,类实现总是获胜。)

例如:

interface IFoo {
    public default String name() {
        return "foo";
    }
}

enum MyEnum implements IFoo {
    A, B, C
}

System.out.println( MyEnum.A.name() );  // Prints "A", not "foo" - superclass Enum wins

你需要考虑一个接口。毕竟,通常的做法是从接口开始,然后提供一个抽象类来提供一些默认实现。如果你有一个接口,你可以让enum实现这个接口。

正如其他人在这里所说的,你不能扩展enum。从设计角度来看,这个解决方案似乎耦合得太紧密了。我建议对此使用更具活力的方法。您可以创建某种行为映射:

Map<Token, Runnable> behaviors;
(这里当然需要一些额外的检查)


最后一点注意:在大多数情况下避免继承您的问题似乎很适合命令模式

将枚举用作受支持操作的逻辑组是一种很好的做法。在我看来,使用单个枚举对所有受支持的操作进行分组将提高代码的可读性。记住这一点,标记枚举应该包含所有支持的操作类型

enum Token
{
   FOO("foo", "do_foo"),
   QUIT("quit", "do_quit"),
   PRINT_STATS("print", "do_print_stats"),
   UNKNOWN("unknown", "unknown")
   .....   

}
考虑创建一个接口参与者,该参与者定义了一个方法,比如act,如下所示:

public interface Actor
{
   public void act();
}
您可以为每个受支持的命令设置一个类,而不是使用单个的Base类来完成很多事情,例如

public class FooActor implements Actor
{
    public void act()
    {
        do_foo(); //call some method like do_foo
    }
}

public class PrintActor implements Actor
{
    public void act()
    {
        print_stats(); //call some print stats
    }
}
最后,将有一个驱动程序代码,它将接收要执行的操作作为输入,初始化相应的Actor,并通过调用act()方法执行该操作

public class Driver
{
   public static void main(String[] args)
   {
      String command; // will hold the input string from the user.

      //fetch input from the user and store it in command

      Token token = Token.parse(command);

      switch(token)
      {
         case FOO:
                   new FooActor().act();
                   break;

         case PRINT_STATS:
                   new PrintActor().act();
                   break;
          .... 

      }


   }
}

这样的设计将确保您可以轻松添加新命令,并且代码保持模块化。

完成本教程的有用链接:谢谢。我读了那本书,但显然没有抓住所有的东西。我将介绍接口方法。喜欢你的头像顺便说一句:)。谢谢@Aubin,-提供了额外的链接。还没看到斑点-但看起来我应该。它看起来是用我喜欢的语言编写的。在类似的情况下,我想从抽象基类继承非平凡的实现,最后我得到了一个枚举作为实例成员。谢谢,我将继续努力。我对Java比较陌生,-所以这种输入非常有用。谢谢。是的,我看了
Map
approach。尝试过,但我想我错过了一些东西-不是我不想进一步研究它,而是想在未来的道路上。。。也许现在就应该这样做。另外,关于“紧密耦合”和“避免继承”。我在“java避免继承”上做了一个快速的网络搜索,发现了这些,但是我还得多读几遍,希望能抓住问题的严重性。很好的一点(我想,我在java只呆了几个星期)。在这个具体案例中,我的问题是,我有很多act的典型50+。相当多的是一个班轮。这意味着50多个文件和50多个类,对吗?或者,我当然只能为那些拥有更庞大代码库的类添加一个类。还有一个要点是重复使用相同的基函数…您可以向枚举中添加一个act方法,而不是switch(token),只需调用token.act();命令集位于三个必须同步的位置:enum、实现的类和“驱动程序”。在一个地方执行命令而忘记另一个地方是很容易的。我可能会节省驱动程序,并将实现的参与者的实例放入枚举器的另一个构造函数参数中。
public class Driver
{
   public static void main(String[] args)
   {
      String command; // will hold the input string from the user.

      //fetch input from the user and store it in command

      Token token = Token.parse(command);

      switch(token)
      {
         case FOO:
                   new FooActor().act();
                   break;

         case PRINT_STATS:
                   new PrintActor().act();
                   break;
          .... 

      }


   }
}