一、多态
多态:可以理解为同一个事物在不同的场合具有不同的形态
分为两种:
-
编译时多态:在编译期间编译器根据函数实参的类型确定要调哪个函数(这个我们之前已经接触过了,和函数重载差不多,是同名函数,但是参数不同)编译时的多态性是通过函数重载或运算符重载来实现的。
-
运行时多态:在程序运行期间才会去判断到底会调用哪个函数。这里我们主要讲的就是动态多态。运行时的多态性是通过虚函数与基类指针共同作用实现的。
作用:
-
静态多态的作用:减少了名字(比如:函数名)的数量,避免了名字空间的污染,对于程序的可读性有很大的好处。
-
动态多态的作用:多态技术允许将基类指针或基类引用指向子类对象,根据对象的动态类型来决定调用的是哪个子类中的这个同名方法,从而解决了同名覆盖问题,写出了通用的代码,即扩展性优秀的代码,以适应需求的不断变化。
简单举个例子:
猫 x=new 猫();
动物 y=new 猫();
1.多态的体现
- 父类的引用指向自己的子类对象;
- 父类的引用也可以接收自己的子类对象。
2.多态的前提
必须是类与类之间的关系,要么是继承(extends),要么是实现(implements),通常还有一个前提,就是存在覆盖(重写)。
3.多态的好处
多态的出现大大的提高了程序的可扩展性。但是只能使用父类的引用,访问父类的成员。
4.类型转换(向上转型,向下转型)
- Anmial a=new Cat();//类型提升,向上转型
- Cat c=(Cat)a;//强制将父类的引用转成子类的类型,向下转型
/*
Anmial a=new Anmial();
Cat c=(Cat)a;
此段代码有误;
原因:不能将以前有的东西强制转为现有的东西。
*/
总结:能转换的是父类应用指向自己的子类对象时,该用用可以被提升,也可以被强制转换。
5.多态的应用
instanceof-------一般用于子类的类型有限,当传的类型需要进行其他操作时,必须要确定它的类型,即用到它的特有方法,这时用instaceof进行比较。
多态示例一:
abstract class Animal{
public abstract void eat();
}
class Cat extends Animal{
public void eat(){
System.out.println("猫吃鱼");
}
public void catchMouse(){
System.out.println("猫抓老鼠");
}
}
class Dog extends Animal{
public void eat(){
System.out.println("狗吃骨头");
}
public void kanJia(){
System.out.println("狗看家");
}
}
class duotaiDemo{
public static void main(String[] args){
funcation(new Dog());
funcation(new Cat());
public static void funcation(Animal a){
a.eat();
if(a instanceof Cat){
Cat c=(Cat)a;
c.catchMouse();
}else if(a instanceof Dog){
Dog d=(Dog)a;
d.kanJia();
}
}
}
}
输出结果为:
狗吃骨头
狗看家
猫吃鱼
猫抓老鼠
多态示例二:
描述笔记本,笔记本使用USB鼠标,USB键盘,移动硬盘
定义USB接口,笔记本要使用USB设备,即笔记本在生产时需要预留可以插入USB
设备的USB接口,即就是笔记本具备使用USB设备的功能,但具体是什么USB设备,笔记本
并不关心,只要符合USB规格的设备都可以。鼠标、键盘和移动硬盘要能在电脑上使用,那么鼠标、键
盘和移动硬盘也必须遵守USB规范,不然生产出来无法使用
class DuoTai02{
public static void main(String[] args){
Computer c=new Computer();
c.getUSBConnect1(new Mouse());
c.getUSBConnect2(new KeyBoard());
//好处 降低耦合性
}
}
interface USB{
public void doSometing();
}
class Computer {
public void getUSBConnect1(USB usb){
usb.doSometing();
}
public void getUSBConnect2(USB usb){
usb.doSometing();
}
}
class Mouse implements USB{
public void doSometing(){
System.out.println("鼠标激活可用!");
}
}
class KeyBoard implements USB{
public void doSometing(){
System.out.println("键盘激活可用!");
}
}
class MobleHardDisk implements USB{
public void doSometing(){
System.out.println("移动硬盘激活可用!");
}
}
6.多态中成员的特点
-
多态成员变量
当子父类中出现同名的成员变量时,多态调用该变量时:
编译时期:参考的是引用型变量所属的类中是否有被调用的成员变量。没有,编译失败。
运行时期:也是调用引用型变量所属的类中的成员变量。
简单记:编译和运行都参考等号的左边。编译运行看左边。 -
多态成员函数
编译时期:参考引用变量所属的类,如果没有类中没有调用的函数,编译失败。
运行时期:参考引用变量所指的对象所属的类,并运行对象所属类中的成员函数。
简而言之:编译看左边,运行看右边。 -
多态静态函数
多态调用时:编译和运行都参考引用类型变量所属的类中的静态函数。
简而言之:编译和运行看等号的左边。其实真正调用静态方法是不需要对象的,静态方
法通过类直接调用。
【结论: .】
1.对于成员变量和静态函数,编译和运行都看左边。
2.对于成员函数,编译看左边,运行看右边。
二、内部类
1.内部类由来:
在我们描述一个事物的时候(类) 发现,该事物当中又存在一个其他的事物
那么外面的这个事物叫做外部类, 里面的事物叫做内部类
2.内部类的作用:
- 内部类提供了更好的封装,不允许外部类之外的类访问外部内中的内部类的对象(但可以获取外部类.内部类.class),内部类只有在外部类中才有效,离开外部类后没有任何意义。
- 内部类可以访问外部的的成员变量(包括私有变量)
- 匿名内部类适合用于创建那些只需要使用一次的类。
内部类比外部类多了三个修饰符(都有的是public-共有访问权限,default-包访问权限):private(当前类访问权限),protected(子类访问权限),static,final。因为外部类只有两个作用于包、任何位置。而内部类有四个作用域:同一个类、同一个包、父子类、任何位置。
3.内部类分类
1.静态内部类(static inner class):
只能访问外部类的静态成员变量和静态方法,生成静态内部类的方式为:StaticInner.Inner inner=new StaticInner.Inner();
2.成员内部类(member inner class):
A)可以当做成员变量来看待理解,可以访问外部类的静态与非静态方法和成员变量,
生成成员内部类的方式:Member.MemberInner m=new Member().new MemberInner();
B)若想在成员内部类中访问外部类的变量,语法为:OutClass.this.a
3.局部内部类(local inner Class):
a) 定义在方法里面,只能访问方法中声明的final类型的变量;
b) 这个类要定义成final类型的;
c) 只能在这个方法中new出其对象,对其进行操作。
d) 注意:方法内部的局部变量或局部类都是final类型的。
4.匿名内部类(Anonymous Inner Class):
a) 没有类名,没有构造方法,但是隐式地继承一个父类或者实现一个接口。
b) 通常作为方法参数,在swing中注册监听者用的较多。
class InnerClassDemo{
public static void main(String[] args){
//1.成员内部类 如何调用该内部类中的其他成员
//num想要被访问 必须先创建Inner对象
//Inner对象想创建 必须先存在Inner类
//Inner类又是Outter的一个成员 必须先创建Outter对象
/*
Outter out=new Outter();
Outter.Inner in=out.new Inner();
*/
/*
Outter.Inner in=new Outter().new Inner();
System.out.println(in.num);
in.show();
*/
//成员内部类中无法创建静态成员
//为什么?
//因为静态优先于对象加载进静态方法区
//但是 内部类的静态成员想要进方法区 前提是该类得存在
//该内部类的存在前提是外部类创建对象
//创建外部类的对象之前 静态都已经加载完毕了
//矛盾!
//2.静态内部类当中 如何访问非静态成员
Outter.Inner in=new Outter.Inner();
in.show();
//3.静态内部类当中 如何访问静态成员?
System.out.println(Outter.Inner.haha);
/*
内部类当中如果出现静态 则内部类也必须是静态的
*/
}
}
class Outter{
//类的内容 成员变量 成员函数 静态变量 静态函数
//成员类 静态类
int num=10;
static int haha=30;
public void show(){
System.out.println("Outter show");
}
//this
static class Inner{
//此处 this只能是Inner对象
int num=20;
static int haha=40;
public void show(){
System.out.println("Inner show"+num);
System.out.println(haha);
//Outter.this.show();
System.out.println(Outter.haha);
}
}
}
来源:CSDN
作者:清灵菲儿
链接:https://blog.csdn.net/weixin_45522644/article/details/103478049