多态的应用
多态数组
具体的介绍和使用请理解下面的代码
以下的代码写在一个文件中,所以class没有用public修饰
/*
* 多态的应用:多态数组
*
* 数组的元素类型是父类的类型
* 数组的元素对象是子类的对象
*
* 需求:
* (1)父类,图形Graphic,里面有一个方法getArea()
* (2)子类:园
* (3)子类:矩形
* (4)【对象数组】要用一个数组来装各种图形的对象,并且遍历这些图形,打印他们的面积
*/
public class TestUse1 {
public static void main(String[] args) {
Circle[] arr1 = new Circle[3];//只能装圆的对象
Rectangle[] arr2 = new Rectangle[3];//只能装矩形的对象
//创建数组对象,其实也就是一个容器,创建一个图形的类型的数组
Graphic[] arr3 = new Graphic[3];
//左边的arr3的类型是Graphic,右边赋值的是Circle的对象,这就是对台的引用
arr3[0] = new Circle(3);
//左边的arr3的类型是Graphic,右边赋值的是Circle的对象,这就是对台的引用
arr3[1] = new Circle(2);
//左边的arr3的类型是Graphic,右边赋值的是Rectangle的对象,这就是对台的引用
arr3[2] = new Rectangle(3,2);
for (int i = 0; i < arr3.length; i++) {
System.out.println(arr3[i].getArea());
}
}
}
/*
* 类的概念:体现这一类事情的共同特征,所有的图形都可以求面积
*/
class Graphic{
//图形类
public double getArea() {
//目前没有学抽象类不然直接在这里定义抽象类这样子类必须重写该方法
return 0.0;
}
}
//子类圆
class Circle extends Graphic{
private double radius;
public Circle() {
super();
}
public Circle(double radius) {
super();
this.radius = radius;
}
public double getRadius() {
return radius;
}
public void setRadius(double radius) {
this.radius = radius;
}
@Override
public double getArea() {
return Math.PI*radius*radius;
}
}
//子类矩形
class Rectangle extends Graphic{
private double length;
private double width;
public Rectangle() {
super();
}
public Rectangle(double length, double width) {
super();
this.length = length;
this.width = width;
}
public double getLength() {
return length;
}
public void setLength(double length) {
this.length = length;
}
public double getWidth() {
return width;
}
public void setWidth(double width) {
this.width = width;
}
@Override
public double getArea() {
return length*width;
}
}
多态的参数
同样看下面的代码理解
public class Graphic{
//图形类
public double getArea() {
//目前没有学抽象类不然直接在这里定义抽象类这样子类必须重写该方法
return 0.0;
}
}
//子类圆
public class Circle extends Graphic{
private double radius;
public Circle() {
super();
}
public Circle(double radius) {
super();
this.radius = radius;
}
public double getRadius() {
return radius;
}
public void setRadius(double radius) {
this.radius = radius;
}
@Override
public double getArea() {
return Math.PI*radius*radius;
}
}
//子类矩形
public class Rectangle extends Graphic{
private double length;
private double width;
public Rectangle() {
super();
}
public Rectangle(double length, double width) {
super();
this.length = length;
this.width = width;
}
public double getLength() {
return length;
}
public void setLength(double length) {
this.length = length;
}
public double getWidth() {
return width;
}
public void setWidth(double width) {
this.width = width;
}
@Override
public double getArea() {
return length*width;
}
}
//创建一个三角形的子类
public class TriAngle extends Graphic {
private double s1;
private double s2;
private double s3;
public TriAngle() {
super();
}
public TriAngle(double s1, double s2, double s3) {
super();
this.s1 = s1;
this.s2 = s2;
this.s3 = s3;
}
public double getS1() {
return s1;
}
public void setS1(double s1) {
this.s1 = s1;
}
public double getS2() {
return s2;
}
public void setS2(double s2) {
this.s2 = s2;
}
public double getS3() {
return s3;
}
public void setS3(double s3) {
this.s3 = s3;
}
public double getArea() {
if(s1 > 0 && s2 > 0 && s3 > 0) {
if (s1 + s2 > s3 && s2 + s3 > s1 && s1 + s3 > s2) {
// 海伦公式
double p = (s1 + s2 + s3) / 2;
double s = Math.sqrt(p * (p - s1) * (p - s2) * (p - s3));
return s;
}
}
return 0;
}
}
public class GraphicTools{
/*
* 参数两个图形
*/
public boolean compare(Graphic g1,Graphic g2) {
if(g1.getArea() == g2.getArea()) {
return true;
}else {
return false;
}
}
}
/*
* 多态的应用:多态参数
* 形参是父类的类型
* 实参是子类的类型
*
* 需求:在工具类GraphicTools中,声明一个方法
* 可以比较两个图形对象的面积是否相同。
*/
public class TestUse2 {
public static void main(String[] args) {
GraphicTools gt = new GraphicTools();
Circle c1 = new Circle(1);
Circle c2 = new Circle(1);
//c1,c2是实参
//形参个g1是Graphic类型,实参c1是Circle类型,实参给形参赋值
//隐含的是Graphic g1 = c1; 左边的g1是父类的类型,右边的c1是子类的对象
//隐含的是Graphic g2 = c2; 左边的g2是父类的类型,右边的c2是子类的对象
boolean flag = gt.compare(c1, c2);
System.out.println(flag);
Rectangle r1 = new Rectangle(3,2);
Rectangle r2 = new Rectangle(2,3);
flag = gt.compare(r1, r2);
System.out.println(flag);
TriAngle t1 = new TriAngle(3,4,5);
TriAngle t2 = new TriAngle(3,4,5);
flag = gt.compare(r1, r2);
System.out.println(flag);
flag = gt.compare(t1, c1);
System.out.println(flag);
}
}
类型的转换(向上转型和向下转型)
-
回忆基本类型的数据转换
(1)自动类型转换
byte,short,char -> int -> long->float->double
boolean不参加
(2)强制类型转换
上面的顺序反过来
这个风险就是精度的损失,和溢出的风险。 -
现在:引用数据类型、编译时类型
(1)向上转型
当出现多态引用是,子类的对象就会向上转型为父类的类型
一旦向上转型,通过父类的变量,就无法调用子类“扩展”的方法
(2)向下转型
当吧存在父类的变量中的对象重新赋值给子类的变量时,就得向 下转型。
向下转型是有风险的,可能会发生ClassCastException:类型转换异常 -
如何避免这个异常呢
instanceof
格式为 : 对象 instanceof 类型
判断这个对象是否属于这个类型
具体的理解就好好的理解一下的代码
(下列的代码写在一个文件夹中,所以class没有用public修饰)
/*
* 回忆基本类型的数据转换
* (1)自动类型转换
* byte,short,char -> int -> long->float->double
* boolean不参加
* (2)强制类型转换
* 上面的顺序反过来
* 这个风险就是精度的损失,和溢出的风险。
*
* 现在:引用数据类型、编译时类型
* (1)向上转型
* 当出现多态引用是,子类的对象就会向上转型为父类的类型
*
* 一旦向上转型,通过父类的变量,就无法调用子类“扩展”的方法
*
* (2)向下转型
* 当吧存在父类的变量中的对象重新赋值给子类的变量时,就得向下转型。
*
* 向下转型是有风险的,可能会发生ClassCastException:类型转换异常
*
* 如何避免这个异常呢
* instanceof
* 格式为 : 对象 instanceof 类型
* 判断这个对象是否属于这个类型
*/
public class TestClassCast {
public static void main(String[] args) {
DoorMan d = new DoorMan();
Chinese chinese = new Chinese();
d.welcome(chinese);
American american = new American();
d.welcome(american);
}
}
class DoorMan {
public void welcome(Human h) {// 这个形参是父类的类型
// 如果只是输出问好的话这样子就够了,但是我们还需添加回答问候语
h.say();
// 这个样子的回复肯定不行的,这个样子的回复只能回复中文的,不能匹配起来。
// System.out.println("你好,你吃了吗?");
// h是父类的类型,无法调用子类特有的方法 eat() meet()
if (h instanceof Chinese) {
Chinese c = (Chinese) h;
c.eat();
} else if (h instanceof American) {
American a = (American) h;
a.meet();
}
}
}
class Human {
public void say() {
System.out.println("呵呵");
}
}
class Chinese extends Human {
@Override
public void say() {
System.out.println("你好");
}
public void eat() {
System.out.println("你吃了吗?");
}
}
class American extends Human {
@Override
public void say() {
System.out.println("Hello");
}
public void meet() {
System.out.println("nice to meet you");
}
}