面向对象特征---多态
2020-04-14 本文已影响0人
小疏林er
1、重写
(1)概念:
重写(也叫覆盖,Override)是指在派生类中重新对基类中的虚函数(注意是虚函数)重新实现。即子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变,核心重写。
重写的好处在于子类可以根据需要,定义特定于自己的行为。 也就是说子类能够根据需要实现父类的方法。
Animal.class
class Animal{
String name = "animal";
public void eat() {
System.out.println(name+"都得吃东西");
}
}
Cat.class
class Cat extends Animal{
String name = "小花儿";
public void eat() {
System.out.println(name+"爱吃鱼");
}
}
Dog.class
class Dog extends Animal{
String name = "旺财";
public void eat() {
System.out.println(name+"爱吃肉");
}
public void seeDoor() {
System.out.println(name+"会看门");
}
}
Test_Override.class
public class Test_Override {
public static void main(String[] args) {
Animal a = new Animal();
Animal b = new Cat();
Animal c = new Dog();
Dog d = new Dog();
a.eat();
b.eat();
c.eat();
// c.seeDoor(); 编译时c被认为是Animal,而Animal中没有seeDoor方法
d.eat();
d.seeDoor();
}
}
代码结果
image.png
(2)重写的规则
- 参数列表必须完全与被重写方法的相同。(注意和重载进行区分,重载参数列表一定不同)
- 访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类的一个方法被声明为 public,那么在子类中重写该方法就不能声明为 protected。
- 构造方法不能被重写。(构造方法可以被重载!)
- 父类的成员方法只能被它的子类重写。
- 声明为 final 的方法不能被重写。
- 声明为 static 的方法不能被重写,但是能够被再次声明。
简记为"两同两小一大":
两同:方法名、形参列表同;
两小:子类方法返回值要比父类的更小或者相等,子类方法声明抛出异常应比父类抛出的异常更小或者相等;
一大:子类方法访问权限应比父类方法访问权限更大或相等。
2、多态
(1)、概念:
父类的方法在子类中表现为多种形态,同一个方法调用,由于对象的不同可能会有不同的行为。
(2)、要点
- 多态是方法的多态,不是属性的多态,多态与属性无关。
- 多态的存在有三个必要条件:
I. 继承:只有继承子类才能成父类(保证同一事物)。
II. 方法重写:才能让父类的行为和子类的同一行为,表面上是一个声明,内部 在实现上不一样,叫多种形态。
III. 父类引用指向子类对象。- 父类引用指向子类对象后,用该父类引用调用子类重写的方法,此时多态就出现了。
People p = new Student();
这就是父类引用指向子类对象。(3)多态的四种表现形式
- 方法重载:在同一个类中,同名的方法对应着不同的方法实现,它们的区别就是参数列表的不同。
- 方法重写:主要用于父类和子类中,子类重写父类的方法,导致了不同方法实现,但是方法名和参数列表都相同。
- 抽象类:一个类中的方法只给出了规范,但是并没有具体实现,只能由子类继承后实现。
- 接口:接口是一个抽象类型,是抽象方法的集合。一个类只能继承一个抽象类,而一个类却可以实现多个接口。
(4)多态要注意的细节
- 多态情况下,子父类存在同名的成员变量或同名的静态成员函数时,访问的都是父类成员,除非在同名非静态函数中调用。
- 多态情况下,子父类存在同名的非静态的成员函数时,访问的是子类的成员函数。(这样重写才有意义)
- 多态情况下,不能访问子类特有的成员。需要向下强制转型才可。
3、多态的应用场景
(1)多态用于形式参数类型的时候,可以接受更多类型的数据 。
例如传入多边形,计算多边形面积、周长。
public class Test_OverrideDuobian {
public static void main(String[] args) {
Jvxing j = new Jvxing(10,5);
out(j);
DengyaoTixing d =new DengyaoTixing(4,10,4,5);
out(d);
}
public static void out(Duobianxing d){ //父类引用指向子类对象
d.getLength();
d.getArea();
}
}
abstract class Duobianxing{
public abstract void getLength();
public abstract void getArea();
}
class Jvxing extends Duobianxing{
int width;
int height;
public Jvxing(int width, int height) {
super();
this.width = width;
this.height = height;
}
public void getLength() {
System.out.println("矩形周长为:"+2*(width+height));
}
public void getArea() {
System.out.println("矩形的面积为:"+width*height);
}
}
class DengyaoTixing extends Duobianxing{
int shangdi;
int xiadi;
int height;
int xiebian;
public DengyaoTixing(int shangdi, int xiadi, int height, int xiebian) {
super();
this.shangdi = shangdi;
this.xiadi = xiadi;
this.height = height;
this.xiebian = xiebian;
}
public void getLength() {
System.out.println("等腰梯形的周长为:"+((2*xiebian)+shangdi+xiadi));
}
public void getArea() {
System.out.println("等腰梯形的面积为:"+(shangdi+xiadi)*height/2);
}
}
结果图:
image.png
(2)多态用于返回值类型的时候,可以返回更多类型的数据。
例如通过名字获取不同子类的照片。
public class Test_OverrideYY {
public static Photo getPhoto(String name) {
if(name=="小花儿") {
return new Cat();
}else {
return new Dog();
}
}
public static void main(String[] args) {
Photo p = getPhoto("小花儿");
p.photoGraph();
Photo p1 = getPhoto("旺财");
p1.photoGraph();
}
}
abstract class Photo{
public abstract void photoGraph();
}
class Cat extends Photo{
String name = "小花儿";
public void photoGraph() {
System.out.println(name+"比个耶");
}
}
class Dog extends Photo{
String name = "旺财";
public void photoGraph() {
System.out.println(name+"喊茄子");
}
}
结果图:
image.png