关于Java中面向对象编程(OOP)中的继承、多态和封装的基本概念
父类
import com.renting_house.HouseTool; import java.util.Scanner; /* 相关的业务层 */ public class HouseService { // 数组用来存储其输入的信息,先动态创建数组,不分配空间大小 String[] arr; int count; // 用来统计房屋的空间大小的 // 变量值 private boolean variabel; private String key; // 新增房源的相关信息 private String name; private String phone; private String address; private double MonthlyRent; private String state; Scanner sc = new Scanner(System.in); public HouseService(String key) { this.setKey(key); } // set以及get public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public double getMonthlyRent() { return MonthlyRent; } public void setMonthlyRent(double monthlyRent) { MonthlyRent = monthlyRent; } public String getState() { return state; } public void setState(String state) { this.state = state; } public String getKey() { return key; } public void setKey(String key) { this.key = key; } public boolean getVariabel() { return variabel; // 布尔值的返回类型是true或者false。 固定的不可以进行赋值 } public void setVariabel(boolean variabel) { this.variabel = variabel; } // 新增房源的方法 public void AddHouse() { // 创建工具类对象 HouseTool houseTool = new HouseTool(getKey()); int i = 0; System.out.println("请输入添加房屋的数量:"); count = sc.nextInt(); sc.nextLine(); System.out.println("如果数量添加错误请输入 : n"); key = sc.nextLine(); if (key.equals("n")) { count = 0; System.out.println("请重新输入添加房屋的数量:"); count = sc.nextInt(); sc.nextLine(); } key = null; do { arr = new String[count]; System.out.println("------------------请输入你的选择--------------------"); System.out.print("姓名:"); name = sc.nextLine(); System.out.print("电话:"); phone = sc.nextLine(); System.out.print("地址:"); address = sc.nextLine(); System.out.print("月租:"); MonthlyRent = sc.nextDouble(); sc.nextLine(); // 这是清楚掉nextInt();遗留的换行符 System.out.print("状态:"); state = sc.nextLine(); System.out.println("------------------添加完成--------------------"); if (i < arr.length) { arr[i] = name + "\t" + phone + "\t" + address + "\t" + MonthlyRent + "\t" + state; } // 这里的接受有问题。没有接受到 。 不要在这里使用, // System.out.println(“是否要继续添加 : y/n”); // setKey(key = sc.nextLine()); // System.out.println(getKey()); houseTool.judgement(); } while (getVariabel()); for (String value : arr) { if (value == null) { System.out.println(" "); } System.out.println(value); } System.out.println("-----------------------------"); System.out.println(getKey()); System.out.println(getVariabel()); } public static void main(String[] args) { HouseService houseService = new HouseService("null"); houseService.AddHouse(); } }
子类
/* 工具类 */ public class HouseTool extends HouseService { public HouseTool(String key) { super(key); } // 用于添加出租屋中的逻辑判断 public void judgement() { System.out.println("是否要继续添加 : y/n"); setKey(sc.nextLine()); System.out.println(getKey()); do { if (getKey().equals("n")) { System.out.println(getKey()); setVariabel(false); System.out.println(getVariabel()); break; } if (getKey().equals("y")) { System.out.println(getKey()); setVariabel(true); System.out.println(getVariabel()); break; } else { System.out.println("未检测到有效的指令"); System.out.println("是否要继续添加 : y/n"); setKey(sc.nextLine()); } } while (true); }
输出
true 子类是true x qe wsfc 100.0 zfc null null null null false 在父类中,为什么依旧是false
疑问
true 子类是true 但是 false 在父类中,为什么依旧是false
回答
-
尝试在
HouseService
类(即父类)中使用getVariabel()
时,会返回默认值(通常是false
或未初始化状态),因为在父类中并没有这样的方法或变量。如果想让父类也能够访问并修改这个布尔变量,需要在父类中也定义相应的 getter 和 setter 方法,或者将这个布尔变量设为protected
让子类可以访问,然后在judgement()
方法中直接通过父类引用来操作这个变量。
在父类中也定义相应的 getter 和 setter 方法
-
对象状态与实例变量: 在Java中,对象的状态是由其类中的实例变量(也称为字段)所决定的。当一个类继承自另一个类时,子类继承了父类的所有非私有(non-private)方法和变量(包括保护的protected和默认的包级别访问权限的变量)。但是,继承并不意味着子类对象与父类对象共享同一个实例变量;相反,每个对象实例都有自己的一套实例变量副本。
-
方法覆盖(Overriding)与实例变量: 在您的例子中,您并没有覆盖任何方法(除非
HouseService
类中有一些未在代码中显示的方法被您重写了)。但更重要的是,实例变量的值是由具体对象实例的状态所决定的,而不是由类的继承关系决定的。因此,无论您在子类还是在父类中访问一个实例变量,您都将得到与当前对象实例相关的值。 -
当前对象的实例相关值。这和很重要,这也是为什么,true 子类是true 但是 false 在父类中,为什么依旧是false。尽管继承了。但是在不同对象里面,等到的都是当前对象实例相关的值
更加准确的解释是
-
如果父类有一个实例变量,并且您在父类对象中将其设置为
false
,在子类对象中将其设置为true
(假设子类没有隐藏这个变量),那么这两个对象将分别拥有false
和true
的值,因为它们是两个完全不同的对象实例。重要的是要理解,即使子类继承了父类,子类对象中的实例变量值也不会影响父类对象中的实例变量值,因为它们是独立的对象实例。
-
一个更准确的表述可能是:“尽管子类继承了父类,但子类对象和父类对象中的实例变量值仍然是各自独立的,由各自对象实例的状态决定。
解决
-
正如上述表述
-
尽管子类继承了父类,但子类对象和父类对象中的实例变量值仍然是各自独立的,由各自对象实例的状态决定。
-
可以通过在父类中调用子类的相关函数。并且将其赋值给父类的变量
-
代码 :子类 。
public boolean judgement() { do { System.out.println("是否要继续添加 : y/n"); setKey(key = scanner.nextLine()); System.out.println(getKey()); // 这里我们实际上不需要一个 do-while 循环,因为只需要读取一次输入 if ("n".equals(key)) { return false; } if ("y".equals(key)) { return true; } else { System.out.println("未检测到有效的指令"); } }while (true); }
-
代码 :父类
do { arr = new String[count]; System.out.println("------------------请输入你的选择--------------------"); System.out.print("姓名:"); name = scanner.nextLine(); System.out.print("电话:"); phone = scanner.nextLine(); System.out.print("地址:"); address = scanner.nextLine(); System.out.print("月租:"); MonthlyRent = scanner.nextDouble(); scanner.nextLine(); // 这是清楚掉nextInt();遗留的换行符 System.out.print("状态:"); state = scanner.nextLine(); System.out.println("------------------添加完成--------------------"); if (i < arr.length) { arr[i] = name + "\t" + phone + "\t" + address + "\t" + MonthlyRent + "\t" + state; } variabel = houseTool.judgement(); } while (variabel);
-
如上述代码的显示;父类中调用子类的相关函数。并且将其赋值给父类的一共变量。(这样就子类和父类的布尔值就是一样的)
-
注意:直接在父类中调用子类的方法通常不是一个好的设计,因为它违反了面向对象设计中的一个基本原则:封装和抽象。