一、多态
多态的概念 多态可以理解为事物存在的多种体现形态。例如动物中的猫,狗。 猫 a=new 猫(); 可是猫也是动物中的一种,那么也可以这么定义 动物 a= new 猫();这里的动物类就是从猫狗中抽取出相同的属性组合起来的。
1、多态的基本体现
父类或者接口的引用指向或者接收自己的子类对象。动物 a= new 猫();类型提升,向上转型。
2、多态的作用
多态的存在提高了程序的扩展性和后期可维护性。
3、多态的前提
类与类之间必须存在关系,要么继承,要么实现;存在覆盖操作。
4、多态的弊端
只能使用父类的引用访问父类的成员。
如何调用子类特有方法呢?
强制将父类引用转换成子类类型。 猫 c=(猫)a;但是不能将父类对象转换成子类对象 即动物 b=new 动物(); 猫 e=(猫)b;
兄弟之间不能转换 本例即猫不能转换成狗。当在程序中执行向下转型时,如果父类对象不是子类对象的实例,即会发生类型转换异常。所以在执行向下转换之前,要想判断父类对象是否为子类对象的实例,这个判断通常使用instanceof操作符来完成。实例,a instanseof b 其返回值是boolean类型的。
package com.itheima;
/*
毕老师和毕姥爷的故事
*/
class 毕姥爷{
void 讲课(){
System.out.println("管理");
}
void 钓鱼(){
System.out.println("钓鱼");
}
}
class 毕老师 extends 毕姥爷{
void 讲课(){
System.out.println("Java");
}
void 看电影(){
System.out.println("看电影");
}
}
class DuoTaiTest{
public static void main(String[] args){
毕老师 x = new 毕老师();
x.讲课(); //Java
x.看电影(); //看电影
毕姥爷 y = new 毕老师();
y.讲课(); //Java
y.钓鱼(); //钓鱼
毕老师 z = (毕老师)y;
z.看电影(); //看电影
}
}
结果如下:
5、多态时成员的特点:
(1)、成员变量
编译时:参考引用型变量所属的类中是否有调用的成员变量。有,编译通过,没有,编译失败。
运行时:参考引用型变量所属的类中是否有调用的成员变量,并运行该所属类中的成员变量。
简单说:编译和运行都参考等号的左边。
(2)、成员函数
编译时:参考引用型变量所属的类中是否有调用的函数。有,编译通过。没有,编译失败。
运行时:参考的是对象所属的类中是否有调用的函数。
简单说:编译看左边,运行看右边。
(3)、静态函数
编译时:参考的是对象所属的类中是否有调用的函数。
运行时:参考的是对象所属的类中是否有调用的函数。
简单说:编译和运行看左边。
非静态有函数覆盖地特点
6、多态的应用
示例:
package com.itheima;
/*
需求:
电脑运行实例,
电脑运行基于主板。
*/
interface PCI
{
public void open();
public void close();
}
class MainBoard
{
public void run()
{
System.out.println("mainboard run ");
}
public void usePCI(PCI p)//PCI p = new NetCard()//接口型引用指向自己的子类对象。
{
if(p!=null)
{
p.open();
p.close();
}
}
}
class NetCard implements PCI
{
public void open()
{
System.out.println("netcard open");
}
public void close()
{
System.out.println("netcard close");
}
}
class SoundCard implements PCI
{
public void open()
{
System.out.println("SoundCard open");
}
public void close()
{
System.out.println("SoundCard close");
}
}
class DuoTaiDemo
{
public static void main(String[] args)
{
MainBoard mb = new MainBoard();
mb.run();
mb.usePCI(null);
mb.usePCI(new NetCard());
mb.usePCI(new SoundCard());
}
}
结果运行如下:
二、内部类
内部类的概念:将一个类定义在另一个类的里面,里面那个类就称为内部类(内置类,嵌套类)。内部类分为成员内部类,局部内部类,匿名类等。
1、成员内部类
内部类只有定义在成员位置上,才可以被private、static成员修饰符修饰。被static修饰的内部类只能访问外部类中的静态成员。
内部类可以访问外部类的成员,包括私有;格式为 外部类名.成员
外部类要访问内部类,要先创建内部类对象。 格式为 外部类名.内部类名 变量名 =外部类对象.内部类对象;
2、局部内部类
定义在类的方法中或定义在类中的任意作用域内的类叫做局部内部类。
class Test
{
int i;
public void show(final int a ){
class Inner{
Inner()
{
i=a;
System.out.println(i);
}
}
Inner in = new Inner();
}
public static void main(String[] args)
{
Test test=new Test();
test.show(10);
}
}
运行结果 打印10 。
从结果看出
1、内部类定义在局部时,不可以被成员修饰符修饰;但是不可以访问它所在局部中的变量。只能访问被final修饰的局部变量。
这里需要注意:
如果内部类是静态的,内部类成员也是静态的,可以不用创建内部类对象,直接调用。但是如果内部类中定义了静态成员,该内部类也必须是静态的!
3、匿名内部类
定义:就是内部类的简化写法。
前提:内部类可以继承或实现一个外部类或者接口。
格式:new外部类名或者接口名(){覆盖类或者接口中的代码,(也可以自定义内容。)}
简单理解:就是建立一个带内容的外部类或者接口的子类匿名对象。
什么时候使用匿名内部类呢?
通常使用方法是接口类型参数,并且该接口中的方法不超过三个,可以将匿名内部类作为参数传递。
好处:增强阅读性。
示例如下:
package com.itheima;
abstract class Demo{
abstract void show();
}
class Outer{
int a=1;
void method(){
new Demo() {
@Override
void show() {
// TODO Auto-generated method stub
System.out.println("show......" + a);
}
}.show();
}
}
public class NiMingDemo {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
new Outer().method();
}
}
运行结果输出 show……1