大象进冰箱案例学习Java面向对像及源代码(二)


在上次我写了下最简单的通过大象进冰箱的例子学习面向对象,这次我在上次的 例子上,进一步修改,学习抽象类。

抽象类实现大象进冰箱

首先,我们简单介绍一下,我理解的抽象类:

  1. 抽象类用关键字abstract修饰;
  2. 抽象类中可以包含抽象方法,抽象方法也用关键字abstract修饰,并且抽象方法没有方法体(我们要区别开空方法体 {} 和控方法体的区别),不用实现也不能实现;当然也可以有非抽象的方法,并且有方法体;
  3. 其他类可以继承一个抽象类,该类就称为这个抽象类的子类,并且这个子类必须实现父类中的抽象方法;
  4. 每个子类只能继承一个抽象类;
  5. 抽象类不能被实例化;

abstract抽象类

该例子中含有的类有:

  1. Animal.java
  2. Box.java
  3. Elephant.java
  4. Cat.java
  5. IceBox.java
  6. Cage.java
  7. Person.java
  8. Action.java
  9. Client.java

前两个 加粗斜体 的类是抽象类,其他的类是普通类。
Cat.java 和 Elephant.java 继承类 Animal.java
IceBox.java 和 Cage.java 继承类 Box.java

下面是代码:

Animal.java

package 第三章.3;

public abstract class Animal { 
   protected double width, height; // 方法中用到的 、本类的、某个对象的属性的数值,因为方法是处理数据的
   // 象牙有多长,腿多粗,什么基因跟enter没有关系,所以不定义
   protected Box aBox; // 对象声明的方法,类名 对象名 ,跟int i;是一个意思;
   // 与局部变量不同的是;在方法外定义,可以穿透任何方法,进入任何方法
   // 局部变量只能在方法内部定义,必须赋值,而此处叫成员变量可以不赋值,有默认值。int 0;double 0.0
   // boolean:false
   private String name;

   public Animal(String name) {
   	super();
   	this.name = name;
   }

   public String getName() {
   	return name;
   }

   public void setName(String name) {
   	this.name = name;
   }

   public double getWidth() {
   	return width;
   }

   public void setWidth(double width) {// 方法的参数变量,用于 方法中 传参,双击它,看下谁变成深色
   	this.width = width; // 参数变量width是this.width = width; 中的=后面的width
   } // this.width = width 中=左边的width是成员变量width
   // 双击this.width中的width会看到上面的两个width变成深色
   // 要给某个类的成员变量赋值,就要用这个类的对象调用成员方法set。比如此处,aElephant.getWidth(1.5);
   // aElehant.getWidth() 就会变成1.5,this就是本类的一个对象的意思
   // 到哪去调用呢?到main()方法中去调用

   public double getHeight() { // get方法被对象调用,最终变成一个值。比如:
   	return height; // get方法要有返回值,方法中要有return语句。
   }

   public void setHeight(double height) {// set方法被对象调用,将参数传入,将参数传给本类的对象
   	// 参数变量的值,传给了成员变量
   	this.height = height;
   }

   public Box getaBox() {
   	return aBox;
   }

   public void setaBox(Box aBox) {
   	this.aBox = aBox;
   }
   public abstract void enter();// 父类在第一次定义时,其成员方法 最好定义成抽象的
   								// 抽象方法是用abstrac修饰,没有方法体,即没有方法体{},
}

上面这个类是抽象类,这个抽象类里面enter() 是抽象方法,用abstract修饰,没有方法体,在下面的类中将具体实现这个抽象类

Elephant.java

 package 第三章.3;

public class Elephant extends Animal{ 
	
	private String name;
	
	public Elephant(String name) {
		super(name);
		this.name = name;
	}

	public void enter() {					//具体类中的成员方法,要覆盖抽象父类中的抽象内容。就是说 要有内容
		if((width<aBox.width)&&(height<aBox.height)) {
			System.out.println(this.name+"笨重地进入");
			System.out.println(this.name+"的尺寸:");
			System.out.println(width);
			System.out.println(height);
			
			System.out.println(aBox.getName()+"的尺寸:");
			System.out.println(aBox.width);
			System.out.println(aBox.height);
		}
		//变量3种:成员变量、参数变量、局部变量。作用:成员变量是对象的属性。参数变量为方法传参。局部 变量在方法中临时使用。
		//声明位置:成员变量在所有的方法之外,参数变量在方法后面的括号中,局部变量在方法中。赋值:成员变量不比赋值,有默认值。
		//参数变量在main()方法中传入数值。局部变量在方法中必须赋值。
	}
}

Cat.java

package 第三章.3;

public class Cat extends Animal {

   //Animal中的关于width,height,name的声明,及set,get方法都会继承过来
   
   private String name;
   public Cat( String name ) {  //不能继承Animal(String name) ,所以,子类的构造必须单独有
   	super(name);			 //super就是Animal的意思,如果改成Animal不行,考试,第一句
   	this.name = name;    
   }
   @Override
   	public void enter() {  //因为cat是具体类,所以enter必须实现父类的抽象方法
   						   // 非abstract,要有具体的方法即{}
   		if((width<aBox.width)&&(height<aBox.height)) {
   			System.out.println(this.name+"轻轻地进入");
   			System.out.println(this.name+"的尺寸:");
   			System.out.println(width);
   			System.out.println(height);
   			
   			System.out.println(aBox.getName()+"的尺寸:");
   			System.out.println(aBox.width);
   			System.out.println(aBox.height);
   		}	
    }
}

Box.java

package 第三章.3;

public abstract class Box {
   protected String name;
   protected double width,height;	 //private表示私有,只能在
   						
   public String getName() {
   	return name;
   }

   public void setName(String name) {
   	this.name = name;
   }

   public Box(String name) {
   	super();
   	this.name = name;
   }

   public double getWidth() {
   	return width;
   }

   public void setWidth(double width) {
   	this.width = width;
   }

   public double getHeight() {
   	return height;
   }

   public void setHeight(double height) {
   	this.height = height;
   }
   
   public abstract void open(); //变成抽象的目的,是不让子类继承
   							 //避免继承,像瘟疫一样,继承的目的不是为了节省代码,而是为了多态
   public abstract void close();//抽象类中的方法,可以使抽象的,也可以是非抽象的,加上set,get方法
}

这个类抽象类中,open() 和 close() 是抽象方法,和上面一样,在下面的类中具体实现

IceBox.java

package 第三章.3;

public class IceBox extends Box{
   
   public IceBox(String name) {
   	super(name);
   }

   public void open() {
   	System.out.println(this.name+"门被打开");
   }
   
   public void close() {
   	System.out.println(this.name+"门被关闭");
   }
}

Cage.java

package 第三章.3;

public class Cage extends Box {
   
   
   public Cage(String name) {
   	super(name);
   }
   @Override
   public void open() {				//继承Box,Box中的抽象方法在子类中自动变成具体的方法
   									//因为Cage不是abstract的。
   	System.out.println(this.name+"门被打开");
   }
   @Override
   public void close() {
   	System.out.println(this.name+"门被关闭");
   }
}

Action.java

 package 第三章.3;

public class Action {//剧本里有三个实体,所以三个实体类的变量在这里都要声明
					//每个系统都要包括实体类,以及将众多实体类串起来
	private Animal aAnimal; //要能变化,必须用抽象类的变量,
	private Box aBox;
	private Person aPerson;
	
	private String name;
	public Action(String name) {
			super();
			this.name = name;
	}
	
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
	public Animal getaAnimal() {
		return aAnimal;
	}

	public void setaAnimal(Animal aAnimal) {
		this.aAnimal = aAnimal;
	}

	public Box getaBox() {
		return aBox;
	}

	public void setaBox(Box aBox) {
		this.aBox = aBox;
	}

	public Person getaPerson() {
		return aPerson;
	}
	public void setaPerson(Person aPerson) {
		this.aPerson = aPerson;
	}

	public void action() {
		System.out.println(this.getName());
		aPerson.pull();
		aBox.open();
		aAnimal.enter(); //如果不用继承,这里就要改成猫,cat。回头可能有要改成aDog,、、面向对象编程,即面对抽象类的变量编程
		aPerson.push();		//我们想除了客户端可以改以外。其他计蓝图不改。
		aBox.close();	//开闭原则:对修改关闭,对增加开放,面向抽象编程,抽象类和接口
		
	}
}

Person.java

package 第三章.3;

public class Person {		//人的属性与大象进冰箱没有关系,所以不定义成员变量,只定义成员方法

	private String name;
	public Person(String name) {
		super();
		this.name = name;
	}

	public void pull() {//平常我们说的开门关门,那么开门和关门是定义在冰箱还是人类中呢?
		//原则:开门 用到的尺寸属于哪个类,就定义在哪个类里面。这里属于冰箱,所以开关门的方法定义在冰箱中。而不是人这个类中。
		//再比如:购物车中买两支钢笔,钢笔数量可以加1,但是钢笔的种类并不加1
		System.out.println(this.name+"拉门");
	}

	public void push() {
		System.out.println(this.name+"推门");
	}
}

Client.java

package 第三章.3;

public class Client {
	public static void main(String[] args) {  
		
		// TODO Auto-generated method stub
		Action aAction;
		Animal aAnimal;
		Box aBox;
		Person lurenjia;
		
		aAction = new Action("场景一");
		
		//场景一:泰国大象,路人甲,新飞冰箱
		aAnimal = new Elephant("泰国大象"); //new表示大象已经牵过来,在内存中已分配空间,默认值null已有
											 //如果没有带参数的构造方法。Java 默认给无参的构造方法,Elephant()
											 //之前我们没有定义,也没有出错,但一旦定义了带参数构造函数,系统不再
											 //默认给无参数的构造函数,此处构造方法再无参就会出错
		aBox = new IceBox("新飞冰箱");			//冰箱已放好
		lurenjia = new Person("路人甲");        	//拉冰箱门的人已准备好
											  //以上都是现实中,或在内存中已经存在的活生生对的对象,但和剧本中的对象没有关联
											  //Client类之外的类就是剧本、蓝图、规划图、计划书、抽象的、服务器类
											  //Client类中目前所有的成员变量和Action中的虽然同名的成员变量不是一回事
											  //谁建立的Client类中的成员变量和Action中的成员变量之间的关系?set
											  //那个类拥有这些成员变量,他的对象就调用set方法。Action类拥有aElephant
											  //就用aAction调用set方法,设置aElephant。
		
		aAction.setaAnimal(aAnimal);    	  //把Action内容中的
		aAction.setaBox(aBox);
		aAction.setaPerson(lurenjia);
		
		aAnimal.setaBox(aBox);
		aAnimal.setWidth(1.0);
		aAnimal.setHeight(1.8);
		aBox.setWidth(1.5);
		aBox.setHeight(2.0);
		
		aAction.action();

		aAction = new Action("场景二");
		//场景二:猫、笼子、路人甲
		aAnimal  = new Cat("波斯猫"); //原先Elephant aElephant = new Elephant();
									//现在左边是父类的变量(注意不是对象),右边是子类对象
									//上转型,即右边子类的对象上转型的变量
									//右边是儿子,左边是父亲,考试
									//多态,左边一个父类类型的aAnimal可以充当大象,猫,狗
									//多种子类对象
		aAnimal.setWidth(0.2);								
		aAnimal.setHeight(0.2);									 		
		
		lurenjia = new Person("路人甲");   
		
		aBox = new Cage("笼子");
		
		aAction.setaAnimal(aAnimal);    
		aAction.setaBox(aBox);
		aAction.setaPerson(lurenjia);
		
		aAnimal.setaBox(aBox);
		aAnimal.setWidth(1.6);
		aAnimal.setHeight(1.8);
		aBox.setWidth(1.8);
		aBox.setHeight(2.0);
		
		aAction.action();
	}
}

执行结果

场景一
路人甲拉门
新飞冰箱门被打开
泰国大象笨重地进入
泰国大象的尺寸:
1.0
1.8
新飞冰箱的尺寸:
1.5
2.0
路人甲推门
新飞冰箱门被关闭
场景二
路人甲拉门
笼子门被打开
波斯猫轻轻地进入
波斯猫的尺寸:
1.6
1.8
笼子的尺寸:
1.8
2.0
路人甲推门
笼子门被关闭

简单分析

在这个例子的第一版是,忘记写分析了,在这里补充下:
首先创建类Person.javaElephant.javaIceBox.java,然后在Action.java类中分别声明三个类的实例,但是没有具体实例化,但是设置了 Set() 方法,在Client.java中我们可以先实例化一下上述的三个对象,并且实例化Action类,然后调用Action的实例的 set() 方法去穿过去。最终可以调用所需类的方法,完成功能。
这个例子相比较与第一版的不同就是,在AnimalBox是抽象类,子类需要动物和容器的类需要继承这个两个类,实现里面的抽象方法;使用这种方法的优点就是:当我们想要改变动物和容器时,我们可以直接创建新的动物的类去继承Animal.java,同样换容器时,我们直接创建新的容器的类去继承Box.java,实现其中的抽象方法即可。

大象进冰箱案例学习Java(三) 中是有关使用接口实现大象进冰箱的例子。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值