5.7对象的上转型对象

这一节是本章(子类与继承)的重点内容。

举个例子:

我们常说“老虎是动物”、“狗是动物”等。动物类是老虎类的父亲,这样说也没有问题,但要注意,当我们说“老虎是动物”的时候,老虎将失去老虎独有的属性和功能。
从人的思维方式上看,“老虎是动物”属于上溯思维

A a;
B b = new B();
a = b;//称a为b的上转型对象。

(1) 上转型对象不能操作子类新增的成员变量(失掉了这部分属性),不能调用子类新增的方法(失掉了一些行为)。
(2) 上转型对象可以访问子类 继承或隐藏 的成员变量,也可以调用子类继承的方法或子类 重写 的实例方法,其作用等价于子类对象去调用这些方法。因此,如果子类 重写了父类的某和实例方法 后,当对象的上转型对象调用这个实例方法时一定是调用了子类 重写的实例方法

注意事项:

  1. 不要将父类创建的对象和子类对象的上转型混淆。
  2. 可以将对象的上转型对象再强制转换到一个子类对象,这时,该子类对象又具备了子类所有的属性和功能。
  3. 不可以将父类创建的对象的引用赋值给子类声明的对象(不能说“人是美国人”)。
  4. 如果子类重写了父类的静态方法,那么子类对象的上转型对象不能调用子类重写的静态方法。
package 第五章;

class A {
	int m;
	int getM(){
		return m;
	}
	int seeM()
	{
		return m;
	}
}
class B extends A {
	int m;
	int getM()
	{
		return m+100;
	}
}
public class Example_5_7 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		B b=new B();
		A a=null;
		b.m=20;
		System.out.println(b.getM());//B类中重写了方法
		a=b;
		a.m=-100;
		System.out.println(a.getM());//上转型对象调用的是重写的方法

		System.out.println(b.seeM());//子类继承的方法调用的是隐藏变量
	}

}

输出:

120
120
-100

5.8继承与多态

多态性是指父类的某个方法被其子类重写的时候,可以各自产生自己的功能行为。

例子:

package 第五章;

public class Example_5_8 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		动物 animal=null ;
		animal = new 狗();
		animal.cry();
		animal = new 猫();
		animal.cry();
	}

}
class 动物{
	void cry(){

	}
}

class 狗 extends 动物
{
	void cry()
	{
		System.out.println("汪汪汪……");
	}
}
class 猫 extends 动物
{
	void cry()
	{
		System.out.println("喵喵喵……");
	}
}

5.9 abstract类与abstract方法(抽象类与抽象方法)

用abstract 修饰的类或方法,就叫做抽象类或抽象方法。
不能用final 和 abstract 同时修饰一个方法或类 也不能用static 修饰 abstract方法,即 abstract方法必须是实例方法。
类似摘要,方法体是由子类重写。

重点:

  1. abstract 类中可以有 abstract方法 不能有方法体
  2. abstract 类不能用new 运算符创建对象(可以直接声明,但不能用new)
  3. abstract 类的子类,必须有子类,所以不能有final修饰,子类必须重写抽象类方法。
  4. abstract 类的对象作上转型对象,抽象类的对象做子类对象,调用与子类相同
  5. 理解abstract:让开发者注重行为的标准,而不是细节,作用类似于摘要,宏观的战略布局,细节方面交给子类来完善。

举例:

package 第五章;
abstract class GirlFriend
{
	abstract void speak();//不需要方法体
	abstract void cooking();///不需要方法体
}
class ChinaGirlFriend extends GirlFriend//多态用法
{

	@Override
	void speak() {
		System.out.println("你好!\n");
	}

	@Override
	void cooking() {
		System.out.println("我会做烤牛排\n");
	}

}
class AmericanGirlFriend extends GirlFriend//多态用法
{

	@Override
	void speak() {
		System.out.println("Hello, nice to meet you!\n");
	}

	@Override
	void cooking() {
		System.out.println("roast beef");
	}

}
class Boy
{
	GirlFriend friend;
	void setGirlfriend(GirlFriend f)
	{
		friend = f;
	}
	void showGirlFriend()
	{
		friend.speak();
		friend.cooking();
	}
}
public class Example_5_9 {

	public static void main(String[] args) {
		GirlFriend girl =null;
		ChinaGirlFriend f = new ChinaGirlFriend();
		girl = f;//上转型调用子类方法
		Boy boy = new Boy();
		boy.setGirlfriend(girl);
		boy.showGirlFriend();
		AmericanGirlFriend f1 = new AmericanGirlFriend();
		girl = f1;//上转型调用子类方法
		boy.setGirlfriend(girl);
		boy.showGirlFriend();
	}
}

输出:

你好!

我会做烤牛排

Hello, nice to meet you!

roast beef

5.10 难点:面向抽象编程

概念:所谓的面向抽象编程,是指当设计某种重要的类时,不让该类面向具体的类,而是面向抽象类,即所设计类中的重要数据是抽象类声明的对象,而不是具体类声明的对象。

例子:求柱体积

面对用户需求的变化,常规程序中可能会大幅度更改,会很麻烦。可以用抽象类概括用户的相似需求。

//抽象类
public abstract class Geometry
{
    public abstract double getArea();
}
package 柱体体积;

public class Application {

	public static void main(String[] args) {
		Geometry bottom;//抽象对象
		Pillar pillar;//体积对象
		bottom = new Circle(10);//调用子类求底
		pillar = new Pillar(bottom,20);//调用体积类,求体积方法
		System.out.println("圆柱的体积是:"+pillar.getV());
		bottom = new Rectangle(2,5);//调用子类求底
		pillar = new Pillar(bottom,20);//调用体积类,求体积方法
		System.out.println("长方体的体积是:"+pillar.getV());
		bottom = new Sanjiaoxing(4,4);//调用子类求底
		pillar = new Pillar(bottom,20);//调用体积类,求体积方法
		System.out.println("三棱锥的体积是:"+pillar.getV());
	}
}
package 柱体体积;
//体积计算
public class Pillar {
	Geometry bottom;
	double h;
	Pillar(Geometry bottom,double h)//调用自身进行赋值
	{
		this.bottom=bottom;
		this.h=h;
	}
	public double getV()//体积方法
	{
		if(bottom==null)
		{
			System.out.println("没有底");
			return -1;
		}
		else
		{
			return bottom.getArea()*h;
		}
	}
}
package 柱体体积;
//三角形底面积
public class Sanjiaoxing extends Geometry{

	double d,h;
	Sanjiaoxing(double d,double h)
	{
		this.d=d;
		this.h=h;
	}
	public double getArea() {
		return d*h*0.5;
	}

}
package 柱体体积;
//圆底面积
public class Circle extends Geometry{
	double r;
	Circle(double r)
	{
		this.r=r;
	}
	public double getArea() {
		return (3.14*r*r);
	}
}
package 柱体体积;
//矩形底面积
public class Rectangle extends Geometry {
	double a,b;
	Rectangle(double a,double b)//调用自身进行赋值
	{
		this.a=a;
		this.b=b;
	}
	public double getArea() {
		return a*b;
	}
}

5.11 开——闭原则

所谓“开——闭原则”就是让设计的系统应当对扩展开放,对修改关闭。实际上,这句话的本质是:当系统中增加新的模块的时候,不需要修改现有的模块。

设计的核心部分一定是经过精心设计之后确定下来的基本结构,这部分应该是对修改关闭的,即不能因为用户的需求变化而在发生任何变化,因为这部分不是用来应对需求变化的

如果系统的设计遵守了“开——闭原则”,那么这个系统一定是易维护的,因为在系统中怎加模块的时候,不必去修改系统中的核心模块。

文章作者: Hao.Jia
版权声明: 本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Hao.Jia's Blog
Java 学习笔记
喜欢就支持一下吧