构建Java控制台程序的正确方法

its*_*ols 6 java oop language-concepts

我是一名 80 年代的老程序员,精通 C 和 Pascal。我对 Java 及其概念还很陌生。在尝试使用 OOP 技术学习 Java 的新方法时,我对组合应用程序的正确方法感到相当困惑。

我正在尝试使用以下规则构建一个基本程序。

一个组织有自己的内部图书馆。Staff 类是通用的,有姓名和电话。一些员工是图书管理员。其他人都是会员。所以会员和图书馆员是专门的班级。我认为在这种情况下我们称它们为继承或扩展。

现在我正在尝试构建基本功能,例如输入和打印会员记录。我正在尝试构建一个基于文本的菜单。也许稍后我会考虑子菜单。目前它只是一个简单的菜单。

我不知道是否应该使菜单也成为一个对象,但这就是我想我会做的。

考虑到这一点,这就是我所做的。

我的主要程序:

public class Library extends Menus {
    public static void main(String[] args) {
        Menus Start = new Menus();
        Start.ShowMainMenu();

    }
}
Run Code Online (Sandbox Code Playgroud)

StaffClass.java

public class StaffClass {
    private String Name;
    private String Phone;

    public void InputData() {
        Scanner UserInput = new Scanner(System.in);

        System.out.print("Enter staff name "); Name = UserInput.nextLine();
        System.out.print("Enter staff phone number "); Phone = UserInput.nextLine();

    }

    public void PrintData() {
        System.out.println("Name : " + Name);
        System.out.println("Phone : " + Phone);

    }
}//end StaffClass
Run Code Online (Sandbox Code Playgroud)

菜单.java

public class Menus extends MemberClass {

    int c;
    public void ShowMainMenu() {
        Scanner ui = new Scanner(System.in);
        while(1==1) {
            System.out.println("Main menu");
            System.out.println("1. Add student");
            System.out.println("2. Display all");
            System.out.println("3. exit");
            System.out.print("Enter choice"); c = ui.nextInt();

            switch(c) {
                case 1 : getInputs(); /*System.out.println("option 1");*/ break;
                case 2 : ShowAllInfo(); break;
                case 3 : System.out.println("Leaving the program now..."); System.exit(0); break;
                default  : System.out.println("error.");
            }

        }

    }

}
Run Code Online (Sandbox Code Playgroud)

会员类.java

public class MemberClass extends StaffClass {
    int TotalBooks;
    public void getInputs() {
        InputData();
        UpdateTotalBooks();
    }

    public void ShowAllInfo() {
        PrintData();
        System.out.println("total books taken = " + TotalBooks);
    }

    public void UpdateTotalBooks() {
        Scanner ui = new Scanner(System.in);

        System.out.print("Enter number of books "); TotalBooks = ui.nextInt();        

    }

}
Run Code Online (Sandbox Code Playgroud)

这是我编写的第一个 Java 程序,其中包含如此多的类 + 菜单系统。

我的关键问题是这是否是用 Java 组装程序的正确方法还是有其他方法。

请随时提出对代码的最佳选项/更改建议。但我想保留泛化和专业化的概念。

谢谢!

Eri*_*lun 5

您过度使用类 \xe2\x80\x94 类旨在表示数据类型,或者是静态方法的持有者(本质上只是函数)。然而,您正在使用类作为分发函数然后应用虚假继承的手段。另外,您继承Menus 实例化Menus同一个类 \xe2\x80\x94 ,这毫无意义。

\n

换句话说,您不需要仅仅为了继承而使用继承和大量类。在 Java 中,除了大量无能的开发人员过度使用类之外,没有任何其他东西强制或建议过度使用类和继承。

\n

函数,最好是没有副作用/全局状态的函数,容易推理和正确执行。而分散在父类链中的复杂状态变量却是一个令人头痛的捷径。

\n

我会使用一些简单的东西,例如:

\n
public class Library {\n    public static void main(final String[] args) {\n        showMainMenu();\n    }\n\n    int totalBooks;\n\n    public static void showMainMenu() {\n        final Scanner ui = new Scanner(System.in);\n        while (true) {\n            System.out.println("Main menu");\n            System.out.println("1. Add student");\n            System.out.println("2. Display all");\n            System.out.println("3. exit");\n            System.out.print("Enter choice");\n\n            switch (ui.nextInt()) {\n                case 1:\n                    getInputs();\n                    /*System.out.println("option 1");*/\n                    break;\n                case 2:\n                    showAllInfo();\n                    break;\n                case 3:\n                    System.out.println("Leaving the program now...");\n                    System.exit(0);\n                    break;\n                default:\n                    System.out.println("error.");\n            }\n        }\n    }\n\n    public static void getInputs() {\n        inputData();\n        updateTotalBooks();\n    }\n\n    public static void showAllInfo() {\n        printData();\n        System.out.println("total books taken = " + totalBooks);\n    }\n\n    public static void updateTotalBooks() {\n        System.out.print("Enter number of books ");\n        totalBooks = new Scanner(System.in).nextInt();\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

如果您需要将其拆分为不同的模块,请不要使用继承。相反,创建类似State或的东西Database类的东西,并在静态函数之间传递它,这些静态函数可以修改传入的数据,或者,如果您想深入了解函数式编程和不可变数据结构的世界,请返回数据的更改副本:

\n
class State {\n  // make these non-final if you want State to be mutable\n  // (I\'m too lazy to generate getters; and in Scala you don\'t have to)\n  public final int totalBooks = 0;\n  public final String someOtherState = "hello";\n\n  public State(final int totalBooks, final String someOtherState) {\n    this.totalBooks = totalBooks;\n    this.someOtherState = someOtherState;\n  }\n\n  public State withTotalBooks(final int newValue) {\n    return new State(newValue, someOtherState);\n  }\n  public State withSomeOtherState(final int newValue) {\n    return new State(totalBooks, newValue);\n  }\n}\n\nclass App {\n  public static void main(final String[] args) {\n    State state = new State();\n    // at the top-most level of the program, it\'s OK to use global state\n    state = BookManager.updateNumBooks(state)\n  }\n}\n\nclass BookManager {\n  public static State updateNumBooks(final State state) {\n    return state.withTotalNumBooks(123);\n  }\n\n  // or, if State is mutable:\n  public static void updateNumBooks(final State state) {\n    // UI code here\n    state.totalNumBooks = 123;\n  }      \n}\n\nclass HelloModule {\n  public static State updateMsg(final State state) {\n    // UI code\n    return state.withSomeOtherState("hello world");\n  }\n\n  // or, if State is mutable:\n  public static void updateMsg(final State state) {\n    // UI code\n    state.someOtherState = "hello world";\n  }\n}\n\n// etc\n
Run Code Online (Sandbox Code Playgroud)\n

最后一点:所有这些在简洁的函数式编程 JVM 语言(例如Scala(甚至Frege ))中看起来会更好。如果您必须继续使用 Java,至少请阅读有关函数式编程的内容以及如何在设计程序时从中受益:

\n\n