一 多态性:
1.概念:
多态性是一种允许使用一个界面来访问一类动作的特性,特定的动作可以由不同的具体情况而定(传入 不同的参数)。多态性是发送消息给某个对象,让该对象自行决定响应何种行为。
通过将子类对象引用赋值给超类对象引用变量来实现动态方法调用 多态性通过允许同一界面指定一类动作减少了程序的复杂度,编译器工作就是选择适用于各个情况的特 定动作,而程序员则无须手动进行选择,使用者仅仅是记得以及利用这个统一的界面
2.多态形成的三个必要条件:
1)有继承,父类定义方法,子类重写方法
2)父类的引用指向子类的对象
3)可以使用参数传递时多态,也可以直接创建对象时多态
多态可以用三个定义和两个方法来总结。三个定义分别是父类定义子类构建、接口定义实现类构建和抽 象类定义实体类构建,而两个方法分别是方法重载和方法重写
。
3.多态分为两种:
1.)编译时多态:方法的重载
2.)运行时多态:JAVA
运行时系统根据调用该方法的实例的类型来决定选择调用哪个方法则被称为行 时多态
4.对象的多态性
继承表示的是
is a
的语义
强调的一个点:编程是对现实世界的模拟体现
public class Test1 {public static void main ( String [] args ) {Fa cc = new Fa ();// 调用的是一个名称为 pp 的方法,但是参数不同执行的处理不同cc . pp (); //Fa...ppcc . pp ( 12 ); //Fa.pp(int)}}class Fa {public void pp (){System . out . println ( "Fa...pp" );}public void pp ( int k ){System . out . println ( "Fa.pp(int)" );}}public class 汽车 extends 车库 {} 错误的public class 学生 extends 人 {} 正确的,因为任何一个学生都是人
一个对象x
有两种形态,猫这类事物即具有猫的形态,又具有着动物的形态,这就是对象的多态性。简单 说就是一个对象对应着不同类型
5.多态在代码中的体现
父类或者接口的引用指向其子类的对象。例如:动物
x=new
猫
()
class 动物 {}class 猫 extends 动物 {}猫 x = new 猫 ();动物 x = new 猫 (); 正确的 , 因为所有的猫都是动物,因为定义 class 猫 extends 动物 {}猫 x = new 动物 (); 错误,不是所有的动物都是猫,因为动物是猫的父类
Object x=new Student();Person x=new Student();Student x=new Student();public class Test1 {public static void main ( String [] args ) {动物 x1 = new 动物 ();动物 x2 = new 猫 (); // 猫 extends 动物,表示猫具有动物的所有特性,同时猫具备一些自己都有的特性// x2.play(); 语法报错的原因是:编译器类型和运行时类型的问题}}class 动物 {}class 猫 extends 动物 {public void play () {System . out . println ( " 使劲的抓老鼠 ...." );}}
二 this和super的用法:
this用于指代当前对象,
super
用于指代父类的内存空间的标识
1.this
关键字
this
代表其所在函数所属对象的引用。换言之,
this
代本类的对象的引用 ;当成员变量和局部变量重名,可以用关键字this
来区分,
this
就是所在函数所属对象的引用 ,对象调用了this
所在的函数,
this
就代表哪个对象。一般方法调用默认加
this ,通过this
在构造函数中调用其他构造函数的时候,只能定义在构造函数的第一行,因为初始化动作 要先执行,否则就会报错
2.super
关键字
当本类的成员和局部变量同名用
this
区分,当子父类中的成员变量同名用
super
区分父类
当子父类中出现成员函数一模一样的情况,会运行子类的函数。这种现象,称为覆盖操作,这是函
数在子父类中的特性。在子类覆盖方法中,继续使用被覆盖的方法可以通过
super.
函数名获取
this()
表示调用当前类中的另外一个构造器
,()
中可以带有参数;
super()
表示调用父类中的某个构造
器,
()
中可以带有参数
动物 dw = new 猫();
dw.play();//如果猫类中没有定义play方法,则执行的是从动物类中继承的play方法;如果猫类中也
定义play方法,则最终执行的是猫类中定义的方法
//dw.抓苍蝇()语法错误,因为在编译时系统识别dw为动物类型,所以没有这个方法的定义
if (dw instanceof 猫) {
((猫)dw).抓苍蝇(); //强制类型转换后则可以调用猫类中所定义的特殊方法,否则只能调用动物
类中定义的方法
}
public class Test1 {
public static void main(String[] args) {
需要使用动物的类 tt=new 需要使用动物的类();
tt.pp(new 动物());
tt.pp(new 猫());
}
}
class 需要使用动物的类 {
public void pp(动物 dongwu){ //假设定义方法时参数使用pp(猫 dongwu),当前程
序就和猫类耦合了,如果需要切换到狗则必须修改源代码。但是参数类型为动物,则不管是猫还是
狗都能接收
dongwu.play();
}
}
3.this()
和
super()
this()
表示调用当前类中的另外一个构造器
,()
中可以带有参数
super()
表示调用父类中的某个构造器,
()
中可以带有参数
4.new
子类
()
的执行过程
首先上溯子类的所有祖先类,然后再从上向下逐步执行各个层次父类的构造器
Object—
爷爷的构造
器
—
父亲的构造器
;
最后才执行子类自己的构造器
因为每个类的构造方法中默认第一句话为
super()
表示调用父类的无参构造器,除非编程
super
。
特殊情况
:
5.this和super的三种用法:
1、从语义的角度上说,
this
用于指代当前对象;
super
用于指代父类对象
1、
this()
表示调用另外一个构造器
,super()
表示调用父类中的某个构造器,
()
中的参数决定调用的是哪个 构造器
2、
this.
成员属性用于表示当前对象的某个成员,一般用于局部变量和属性名称一致的场景下。
super.
成 员属性用于表示父类中定义的某个属性,一般用于子类中覆盖定义了某个父类属性的场景下。
3、
this.
成员方法
()
用于表示当前对象的某个成员方法;
super.
成员方法
()
用于表示当前类的父类中定义 的某个成员方法,一般用于覆盖定义时【就近原则】。
4、在
static
方法中不允许使用
this/super
之类关键字
三 面向对象设计思想的要点:
认为客观世界由各种对象组成,任何事物都是对象,复杂的对象可以由比较简单的对象以某种方式
组合而成 把所有对象都划分成各种对象类,每个对象类都定义了一组数据和一组方法 ;按照子类与父类的关系,把若干个对象类组成一个层次结构的系统 对象彼此之间仅能通过传递消息互相联系
四 类间多态和类内多态:
多态是同一个行为具有多个不同表现形式或形态的能力。多态就是同一个接口,使用不同的实例而执行 不同操作
1.类间多态性
父子类之间的一种多态型,例如:动物
x = new
猫
()
public class Test1 {public static void main ( String [] args ) {
2.方法调用中的限制:
针对一个类对象有两种类型,一种称之为编译期类型,编译时系统识别对象的类型,”
动物
x = new 猫()”
在编译时,系统识别
x
是动物类别的,所以只能调用动物类定义的方法,而不能调用猫中特殊 的方法。另外一种称之为运行时类型,也就是当程序运行系统识别的类型,new
谁就是谁
覆盖的方法一定不能是
private
的
3.类内多态性
在一个类对象上调用相同名称的方法,但是当参数不同时执行不同的动作
Animal a1=new Cat();
A a=new A();
a.eee(a1);
}
}
class A{
public void eee(Animal animal){
animal.eat();
}
}
class Animal{
public void eat(){
System.out.println("Animal.eat()");
}
}
class Cat extends Animal{
@Override
public void eat() {
System.out.println("就是爱老鼠");
}
}
class Dog extends Animal{
@Override
public void eat() {
System.out.println("就是爱肉骨头");
}
}
public class Test2 {
public static void main(String[] args) {
A2 a=new A2();
// a.pp();
// a.pp(12);
a.pp("shitou");
}
}
class A2 {
public void pp() {
System.out.println("A2.pp()");
}
public void pp(Integer k) {
System.out.println("A2.pp(int)");
}
public void pp(Object kk) {
System.out.println("A2.pp(String)");
五 方法的重写和重载:
要求:方法的名称一致。
public void pp(int k1,String k2){}
public void pp(String k1,int k2){}
}
public class Test1 {
public static void main(String[] args) {
Fa ff=new Fa();
ff.pp(new Integer(123)); //原则:最佳匹配原则
ff.pp(1.234);
}
}
class Fa {
public void pp() {
System.out.println("Fa.pp()");
}
public void pp(Number kk){
System.out.println("Fa.pp(Number)");
}
public void pp(Integer kk){
System.err.println("Fa.pp(Integer)");
}
}
public class Test1 {
public static void main(String[] args) {
Fa ff = new Fa();
ff.pp(); //最佳匹配原则
}
}
class Fa {
public void pp() {
System.out.println("Fa.pp()");
}
public void pp(int... pages) {// 不确定个数的参数
System.out.println("Fa.pp(int...)");
}
}
六 方法的重写(覆盖):
要求:方法的名称一致
方法的重写
(
覆盖
)
一定发生在父子类之间
执行规则:new
谁运行谁的方法,和声明的类型无关
方法的覆盖定义要求方法名称一致
方法的参数一致
(
个数、类型、顺序
)
,和参数名称无关
顺序一致的问题
,
系统识别方法依靠是方法名称和参数类型列表,和方法参数的名称无关。例如这里
系统识别的方法为
ear(String,String)
。要识别顺序还得依靠类型的区别,例如
eat(int,double)
和
eat(double,int)
public class Test4 {
public static void main(String[] args) {
F4 f=new F4(); f.pp(10);
S4 s=new S4(); s.pp(10);
F4 fs=new S4(); fs.pp(10);
}
}
class F4 {
public void pp(int k) {
System.out.println("F4.pp(int)");
}
}
class S4 extends F4 {
public void pp(int k) { //子类中定义的同名同参数的方法覆盖了父类中的方法定义,如
果需要调用父类中的方法则需要使用super.pp(k)进行调用
System.out.println("S4.pp(int)");
}
}
@Override注解可以使IDE工具在编译源代码时进行检查,如果有手写错误则IDE工具报错
1
类型一致的问题
class Fa {
public void eat(Integer kk) {
System.out.println("Animal.eat()");
}
}
class Son extends Fa {
@Override
public void eat(Number kk) { //类型必须一致,即使父类类型都不可以,int和
Integer简单类型和包装类型也不可以。这里去除@override注解则不会有语法错误,这里不是
方法的重写,是方法的重载
System.out.println("就是爱老鼠");
}
}
七 多态的优点:
消除类型之间的耦合关系
可替换性、可扩充性
接口性、灵活性、简化性