专业的JAVA编程教程与资源

网站首页 > java教程 正文

初识Java—(二十)多态的示例(java中多态的含义)

temp10 2024-09-27 22:54:16 java教程 12 ℃ 0 评论

继承是实现类重用的重要手段,但是继承带来了一个最大的坏处:破坏封装。相比之下,组合也是实现类重用的重要方式,而采用组合方式来实现类重用并能提供更好的封装。下面详细介绍继承和组合之间的联系与区别。

5.8.1 使用继承的注意点

子类扩展父类时,子类可以从父类继承得到Filed和方法。如果访问权限允许,子类可以直接访问父类的Field和方法,相当于子类可以直接复用父类的Field和方法。继承带来了高度复用的同时,也带来了一个严重的问题:那就是继承严重破坏了父类的封装性。封装:每个类都不可以随意访问其父类的Field和方法,父类只需要暴漏必要的方法给其他类使用。但是在继承关系中,子类可以直接访问父类的Field和方法,从而造成子类与父类的严重耦合。

初识Java—(二十)多态的示例(java中多态的含义)

父类的实现细节对于子类来说不再透明,子类可以访问父类的Field和方法,并可以改变父类的方法的实现细节,从而导致子类可以任意的篡改父类的方法和属性(Field)

举例1:

package com.langsin.test;
public class Bird {
public String name = "小鸟";
public void fly(){
System.out.println(this.name+"可以在天空中自由飞翔。。。");
}
Public void run(){
this.fly();
}
}

篡改属性:

package com.langsin.test;
public class Ostrich extends Bird {
public void test(){
this.name = "大象"; //任意篡改了父类的属性信息
this.fly();
}
public static void main(String[] args) {
Ostrich os = new Ostrich();
os.test();
}
}

篡改方法:

package com.langsin.test;
public class Ostrich extends Bird {
public void test(){
this.fly();
}
//任意篡改方法
public void fly(){
System.out.println(this.name+"在水中游来游去。。。");
}
public static void main(String[] args) {
Ostrich os = new Ostrich();
os.test();
}
}

对于此种问题,基于保证父类有良好的封装,不会被子类随意改变,设计父类时通常遵循如下规则:

1、 尽量隐藏父类的内部数据,尽量把父类的所有Field都设置成private访问类型,不让子类直接访问父类的Field.

2、 不要让子类可以随意访问、修改父类的方法。父类中作为辅助其他方法的工具方法,应该使用private访问控制符修饰,让子类无法访问该方法。如果父类中的方法需要被外部类调用,则必须以public修饰,但又不希望被子类重写该方法,可以使用final修饰符来修饰,表示最终的方法。如果父类的方法可以让子类重写,但是又不希望被其他类自由访问,可以使用protected来修饰该方法。

3、 不要在父类构造方法中调用将会被子类重写的方法。因为如果方法被子类重写,那么子类在实例化时,会调用父类的构造方法来进行父类初始化时,构造方法中调用的是被子类重写的方法,而不是本身的那个方法。

举例2:

package com.langsin.test;
public class Bird {
Bird(){
this.fly();
}
public void fly(){
System.out.println("小鸟可以在天空中自由飞翔。。。");
}
}
package com.langsin.test;
publicclass Ostrich extends Bird {
public void fly(){
System.out.println("鱼儿在水中游来游去。。。");
}
public static void main(String[] args) {
Ostrich os = new Ostrich(); //在创建子类对象时,父类构造方法调用了被子类重写的方法。
}
}

注意:如果把某些类设置成最终类,即使用final修饰符修饰这个类,那么这个类将不能被当成父类。例如JDK所提供的java.lang.String类,java.lang.System类,都是最终类。

5.8.2 利用组合实现复用

如果需要复用一个类,除了把这个类当成父类来继承之外,还可以把该类当成另外一个类的组成部分,从而允许新类直接复用该类的public方法。因此,不管是继承还是组合,都允许在新类中直接复用旧类的方法。

举例1:

package com.langsin.basic;
//商品类
public class Product {
// 成员变量都是私有的。如果用到多个类中有成员变量是重复的,尽量把成员变量和方法分别开来。
private String p_name;
private String p_price;
private String p_num;
public Product(){}
public Product(String p_name, String p_price, String p_num) {
this.p_name = p_name;
this.p_price = p_price;
this.p_num = p_num;
}
public String getP_name() {
return p_name;
}
public void setP_name(String p_name) {
this.p_name = p_name;
}
public String getP_price() {
return p_price;
}
public void setP_price(String p_price) {
this.p_price = p_price;
}
public String getP_num() {
return p_num;
}
public void setP_num(String p_num) {
this.p_num = p_num;
}
}

package com.langsin.basic;
//订单类
public class Order {
private String orderName;
private String date;
private String orderId;
private double money;
private Product[] prods = null;

Order(String orderName,String date,String orderId){
this.orderId = orderId;
this.date = date;
this.orderName = orderName;
}
public Product[] getProds() {
return prods;
}
public void setProds(Product[] prods) {
this.prods = prods;
}
public String getOrderName() {
return orderName;
}
public void setOrderName(String orderName) {
this.orderName = orderName;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getOrderId() {
return orderId;
}
public void setOrderId(String orderId) {
this.orderId = orderId;
}
public double getMoney() {
return money;
}

public void setMoney(double money) {
this.money = money;
}
public static void main(String[] args) {
Product[] prods = new Product[3];
Product p1 = new Product("笔记本","1200","1");
Product p2 = new Product("电视机","2000","1");
Product p3 = new Product("冰箱","1500","1");
prods[0] = p1;
prods[1] = p2;
prods[2] = p3;
//商品购买完成
Order order = new Order("张三","20151212","CD001");
order.setProds(prods);
//查看此订单的详细信息
System.out.println("订单用户:"+order.orderName +" 订单日期:"+order.date);
System.out.println("此订单的详细商品如下:==================");
for(int i=0;i<order.getProds().length;i++){

Product prod = order.getProds()[i];//
System.out.println("商品名称:"+prod.getP_name()+" 商品价格:"+prod.getP_price()+" 购买数量:"+prod.getP_num());
}
}
}

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表