关于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以及getpublic 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); -
如上述代码的显示;父类中调用子类的相关函数。并且将其赋值给父类的一共变量。(这样就子类和父类的布尔值就是一样的)
-
注意:直接在父类中调用子类的方法通常不是一个好的设计,因为它违反了面向对象设计中的一个基本原则:封装和抽象。
