我是 80 年代的老程序员,精通 C 和 Pascal。我对Java及其概念很陌生。在尝试使用OOP技术学习Java的新方法时,我对将应用程序组合在一起的正确方法感到困惑。
我正在尝试使用以下规则构建一个基本程序。
一个组织有自己的内部图书馆。职员类是一般的,有姓名和电话。一些员工是图书管理员。其他人是成员。因此,会员和图书馆员是专门的班级。我认为在这种情况下,我们称它们为继承或扩展。
现在,我正在尝试构建基本功能,例如输入和打印成员记录。我正在尝试构建一个基于文本的菜单。也许稍后我会考虑子菜单。目前,它只是一个简单的菜单。
我不知道我是否也应该将菜单作为一个对象,但这就是我认为我会做的。
考虑到这一点,这就是我所做的。
我的主要程序:
public class Library extends Menus {
public static void main(String[] args) {
Menus Start = new Menus();
Start.ShowMainMenu();
}
}
员工类.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
菜单.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.");
}
}
}
}
成员类.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();
}
}
这是我第一个将这么多类+菜单系统放在一起的Java程序。
我的关键问题是,这是否是用Java组装程序的正确方法,还是有其他方法。
请随时建议代码的最佳选项/更改。但我想保留概括和专业化的概念。
谢谢!
你过度使用类 — 类旨在表示数据类型,或者作为静态方法(本质上只是函数)的持有者。但是,您正在使用类作为分发函数的方法,然后应用虚假继承。此外,您继承了同一类中的Menus
和Menus
- 这没有任何意义。
换句话说,您不需要仅仅为了继承而使用继承和许多类。在Java中,除了许多不称职的开发人员过度使用强制或建议过度使用类和继承之外
,没有什么。函数,最好是没有副作用/全局状态的函数,更容易推理和正确。而分散在父类链中的复杂状态变量是令人头疼的捷径。
我会使用一些简单的东西,例如:
public class Library {
public static void main(final String[] args) {
showMainMenu();
}
int totalBooks;
public static void showMainMenu() {
final Scanner ui = new Scanner(System.in);
while (true) {
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");
switch (ui.nextInt()) {
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.");
}
}
}
public static void getInputs() {
inputData();
updateTotalBooks();
}
public static void showAllInfo() {
printData();
System.out.println("total books taken = " + totalBooks);
}
public static void updateTotalBooks() {
System.out.print("Enter number of books ");
totalBooks = new Scanner(System.in).nextInt();
}
}
如果需要将其拆分为不同的模块,请不要使用继承。相反,创建类似 State
或 Database
类的东西,并在静态函数之间传递它,这些静态函数要么修改传入的数据,要么,如果你想窥视函数式编程和不可变数据结构的世界,返回数据的更改副本:
class State {
// make these non-final if you want State to be mutable
// (I'm too lazy to generate getters; and in Scala you don't have to)
public final int totalBooks = 0;
public final String someOtherState = "hello";
public State(final int totalBooks, final String someOtherState) {
this.totalBooks = totalBooks;
this.someOtherState = someOtherState;
}
public State withTotalBooks(final int newValue) {
return new State(newValue, someOtherState);
}
public State withSomeOtherState(final int newValue) {
return new State(totalBooks, newValue);
}
}
class App {
public static void main(final String[] args) {
State state = new State();
// at the top-most level of the program, it's OK to use global state
state = BookManager.updateNumBooks(state)
}
}
class BookManager {
public static State updateNumBooks(final State state) {
return state.withTotalNumBooks(123);
}
// or, if State is mutable:
public static void updateNumBooks(final State state) {
// UI code here
state.totalNumBooks = 123;
}
}
class HelloModule {
public static State updateMsg(final State state) {
// UI code
return state.withSomeOtherState("hello world");
}
// or, if State is mutable:
public static void updateMsg(final State state) {
// UI code
state.someOtherState = "hello world";
}
}
// etc
最后要说的是:所有这些在简洁的函数式编程JVM语言(如Scala(甚至Frege))中看起来会更好。如果你必须继续使用Java,至少阅读一些关于函数式编程的知识,以及你如何在设计程序的方式中从中受益:
- http://docs.scala-lang.org/tutorials/scala-for-java-programmers.html
- https://coderwall.com/p/_f74xw/functional-programming-in-java-from-a-scala-addict
- https://code.google.com/p/guava-libraries/wiki/FunctionalExplained
- Functional Java和Guava之间有很好的比较吗?
评论太长,但没有答案。
- 会有课程。希望他们中的许多人。
- 应遵循 Java 命名约定,例如,以小写字母开头的名称方法。
-
StaffClass
是一个糟糕的名字,而只是使用Staff
。 - 考虑以不同的方式为其提供输入:按原样,
Staff
只能由其自己的输入方法填充。但是,数据如何进入Staff
实例应该与Staff
的实际内容完全无关。 - 没有"一种正确的方法"来从Java程序的类中组装出来,甚至没有一种正确的方法来分解责任。但单一责任原则很重要。同样重要的是方法(可能还有类)应该始终在同一抽象级别运行的概念。