面向对象的基本特征:
- 封装的好处:安全、简便
- 继承的好处:代码的复用和扩展
- 多态的好处:增加代码的灵活性
多态:
- 多种形态
多态引用:
- 父类类型 变量 = 子类的对象;
多态表现出来的现象:
- 编译时是父类的类型,运行时是子类的类型;编译时都是按照父类进行编译的,但是运行时看你赋值的是什么类型的子类对象,执行的是该子类重写的方法体。这样的话,因为赋值的可能是各种子类的对象,那么同一个功能就表现出了各种“不同”的具体的实现。
多态的前提:
- (1)继承
- (2)多态引用
- (3)方法的重写
public class TestPolymorphism {
public static void main(String[] args) {
//父类的类型 变量 = 子类的对象;
Person p = new Man();//多态引用
p.eat();
p.walk();
// p.smoke();//错误的,因为p编译时,是按照Person编译的
p.sayHello();
p = new Woman();//多态引用
p.eat();
p.walk();
// p.shopping();//错误的,因为p编译时,是按照Person编译的
p.sayHello();
System.out.println("---------------------------");
Man m = new Man();//本态引用
m.eat();
m.walk();
m.sayHello();
m.smoke();
Woman w = new Woman();//本态引用
}
}
//父类
abstract class Person{
public abstract void eat();
public abstract void walk();
public void sayHello(){
System.out.println("hello");
}
}
class Man extends Person{
@Override
public void eat() {
System.out.println("狼吞虎咽的吃饭");
}
@Override
public void walk() {
System.out.println("大步流星的走路");
}
public void smoke(){
System.out.println("吞云吐雾");
}
}
class Woman extends Person{
@Override
public void eat() {
System.out.println("细嚼慢咽的吃饭");
}
@Override
public void walk() {
System.out.println("婀娜多姿的走路");
}
public void shopping(){
System.out.println("买买...");
}
}
多态的应用之一:多态数组
-
数组的元素类型声明为父类的类型,而元素实际存储的子类的对象。
-
声明一个数组,里面要装圆、矩形、三角形的对象,然后遍历显示他们的面积和周长,最后按照面积排序。
public class TestUse1 {
public static void main(String[] args) {
// Circle[] yuanArr = new Circle[3];//只能装圆对象
Graphic[] arr = new Graphic[3];//这里不是创建Graphic的对象,而是创建数组对象
//隐蔽的多态引用
//左边arr[i]元素是Graphic类型,右边是子类的对象
//左边是父类的变量,右边是子类的对象
arr[0] = new Circle(1.2);
arr[1] = new Rectangle(1, 3);
arr[2] = new Triangle(1, 1, 1);
for (int i = 0; i < arr.length; i++) {
System.out.println("面积:" + arr[i].getArea() + ",周长:" + arr[i].getPrimeter());
}
}
}
abstract class Graphic{
public abstract double getArea();
public abstract double getPrimeter();
}
class Circle extends Graphic{
private double radius;
public Circle(double radius) {
super();
this.radius = radius;
}
public Circle() {
super();
}
//这里是get/set方法,太占地方,我就不粘上来了,大家写的时候不要丢了
public double getArea(){
return Math.PI * radius * radius;
}
public double getPrimeter(){
return 2 * Math.PI * radius;
}
}
class Rectangle extends Graphic{
private double length;
private double width;
public Rectangle(double length, double width) {
super();
this.length = length;
this.width = width;
}
public Rectangle() {
super();
}
//这里是get/set方法,太占地方,我就不粘上来了,大家写的时候不要丢了
public double getArea(){
return length * width;
}
public double getPrimeter(){
return 2 * (length + width);
}
}
class Triangle extends Graphic{
private double a;
private double b;
private double c;
public Triangle(double a, double b, double c) {
super();
this.a = a;
this.b = b;
this.c = c;
}
public Triangle() {
super();
}
//这里是get/set方法,太占地方,我就不粘上来了,大家写的时候不要丢了
public double getArea() {
double p = (a + b + c)/2;
return Math.sqrt(p * (p-a) * (p-b)* (p-c));
}
public double getPrimeter() {
return a + b + c;
}
}
多态的应用之二:多态参数
-
形参是父类类型,实参是子类的对象
-
调用方法时,实参给形参赋值。
-
本例中:
- 形参类型 Animal类型
- 实参类型 Dog和Horse类型
- Animal d = new Dog();
- Animal d = new Horse();
public class TestUse2 {
public static void main(String[] args) {
check(new Dog());//new Dog()匿名对象
check(new Horse());
}
/*
* 检查这是什么动物
*/
public static void check(Animal d){
d.name();
}
}
abstract class Animal{
public abstract void name();
}
class Dog extends Animal{
public void name() {
System.out.println("狗");
}
}
class Horse extends Animal{
public void name() {
System.out.println("马");
}
}