黑马程序员——多态,内部类

------- android培训java培训、期待与您交流! ----------

一.多态

定义:某一类事物的多种存在形态

简单说:就是一个对象对应着不同类型

 

多态在代码中的体现:

父类或者接口的引用指向其子类的对象

 

多态的好处:

提高了代码的扩展性,前期定义的代码可以使用后期的内容

 

多态的弊端:

前期定义的内容不能使用调用后期子类的特有内容

 

多态的前提:

1、必须由关系,继承,实现

2、要有覆盖

 

例如

猫这个对象对应的类型是猫类型

猫 x = new 猫();

同时猫也是动物中的一种,也可以把猫成为动物

动物 y = new 猫();

动物是猫和狗具体事物中抽取出来的父类型

父类型引用指向了子类对象

 

例子

abstract class Animal    //抽象类
{
    abstractvoid eat();
}
class Cat extends Animal
{
    publicvoid eat()
    {
        System.out.println("吃鱼");
    }
    publicvoid catchMouse()
    {
        System.out.println("抓老鼠");
    }
}
class Dog extends Animal
{
    publicvoid eat()
    {
        System.out.println("吃骨头");
    }
    publicvoid kanJia()
    {
        System.out.println("看家");
    }
}
class duotai
{
    publicstatic void main(String[] args)
    {
        //Catc = new Cat();
        //c.eat();
 
        //Dogd = new Dog();
        //d.eat();              以前的写法
       
    }
}


多态的写法

Animal a = new Cat();
a.eat();  


自动类型提升,猫对象提升成了动物类型,但是无法访问(猫的)特有功能

提升扩展性,作用就是限制对特有功能的访问

专业讲:向上转型

 

如果还想用具体动物猫的特有功能

可以将该对象进行向下转型

Cat c = (Cat)a;  //强制将父类的引用,转成子类类型
c.catchMouse();
 


可以写成这样

毕姥爷 x = new 毕老师();
x.讲课();
毕老师 y = (毕老师)x;
y.看电影();


这件事自始至终都是子类对象(毕老师)在进行变化

 

注意:千万不要出现这样的操作,就是将父类对象转成子类类型

我们能转换的是父类应用指向了自己的子类对象时,该应用可以被提升,也可以被强制转换

多态自始至终都是子类对象在做着变化

 

if(a instanceof Cat)

instanceof用于判断对象的具体类型,只能用于引用数据类型判断

Cat处可以写类,也可以写接口

通常在向下转型前,用于健壮性的判断

 

 

多态时,成员的特点:

1,成员变量。

编译时:参考引用型变量所属的类中的是否有调用的成员变量,有,编译通过,没有,编译失败。

运行时:参考引用型变量所属的类中的是否有调用的成员变量,并运行该所属类中的成员变量。

简单说:编译和运行都参考等号的左边。(引用性变量所属的类)

 

2,成员函数(非静态)。

编译时:参考引用型变量所属的类中的是否有调用的函数。有,编译通过,没有,编译失败。

运行时:参考的是对象所属的类中是否有调用的函数。

简单说:编译看左边,运行看右边。(运行就是看子类自己的方法)//函数(方法)覆盖

 

因为成员函数存在覆盖特性。

 

3,静态函数。

编译时:参考引用型变量所属的类中的是否有调用的静态方法。

运行时:参考引用型变量所属的类中的是否有调用的静态方法。

简单说,编译和运行都看左边。

 

其实对于静态方法,是不需要对象的。直接用类名调用即可。

 

例:

class Fu
{
    intnum =3;  // voidshow(){sop("fu");
}
 class Zi extends Fu
{
    intnum =4; // void show(){sop("zi");
}
class DuoTaiDemo
{
    publicstatic void main(String args[])
    {
        Fuf = new Zi();
        System.out.println(f.num);//f.show();
    }
}


此时打印出的为3,因为此时已转型为父类,覆盖只发在在方法(函数)上,如果执行f.show();,则由于覆盖显示zi

 

 

Object:是所有对象的直接后者间接父类,上帝

该类中定义的肯定是所有对象都具备的功能

 

 

二.内部类

 

内部类不是很好理解,但说白了其实也就是一个类中还包含着另外一个类

如同一个人是由大脑、肢体、器官等身体结果组成,而内部类相当于其中的某个器官之一,例如心脏:它也有自己的属性和行为(血液、跳动)

显然,此处不能单方面用属性或者方法表示一个心脏,而需要一个类

而心脏又在人体当中,正如同是内部类在外部内当中

 

实例1:内部类的基本结构

//外部类
class Out {
    privateint age = 12;
   
    //内部类
    classIn {
        publicvoid print() {
            System.out.println(age);
        }
    }
}
 
public class Demo {
    publicstatic void main(String[] args) {
        Out.Inin = new Out().new In();
        in.print();
        //或者采用下种方式访问
        /*
        Outout = new Out();
        Out.Inin = out.new In();
        in.print();
        */
    }
}


运行结果:12

从上面的例子不难看出,内部类其实严重破坏了良好的代码结构,但为什么还要使用内部类呢?

因为内部类可以随意使用外部类的成员变量(包括私有)而不用生成外部类的对象,这也是内部类的唯一优点

如同心脏可以直接访问身体的血液,而不是通过医生来抽血

 

程序编译过后会产生两个.class文件,分别是Out.class和Out$In.class

其中$代表了上面程序中Out.In中的那个 .

Out.In in = new Out().new In()可以用来生成内部类的对象,这种方法存在两个小知识点需要注意

  1.开头的Out是为了标明需要生成的内部类对象在哪个外部类当中

  2.必须先有外部类的对象才能生成内部类的对象,因为内部类的作用就是为了访问外部类中的成员变量

 

内部类访问特点:

1,内部类可以直接访问外部类中的成员,包括私有。

之所以可以直接访问外部类中的成员,是因为内部类中持有了一个外部类的引用

格式: 外部类名.this

2,外部类要访问内部类,必须建立内部类的对象。

 

一般类不可以私有,但内部类可以私有,因为此时内部类是外部类的一个成员

 

访问格式:

1、当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中

可以直接建立内部类对象

格式: 外部类名.内部类名  变量名= 外部类对象.内部类对象;

Outer.Inter bb = new Outer().newInter();
 


内部类能直接访问外部类中成员,因为内部类持有了外部类的引用

外部类名.this

 

2、当内部类在成员位置上,就可以被成员修饰符所修饰

比如,  private:将内部类在外部类中进行封装

static:内部类就具备了static的特性

当内部类被static修饰后,只能直接访问外部类中的static成员,出现了访问局限

在外部其他类中,如何直接访问static内部类的非静态成员呢?

Outer.Inter bb = new Outer().newInter();
 


   

在外部其他类中,如何直接访问static内部类的静态成员呢?

Outer.Inner.function();


 

注意:当内部类中定义了静态成员,该内部类必须是static的

当外部类中的静态方法访问内部类时,内部类也必须是static的

 

当描述事物时,事物的内部还有事物,该事物用内部类来描述

因为内部事物在使用外部事物的内容

 

内部类定义在局部时

class Outer
{
    voidmethod(final int a)   //成员
    {
        classInter  //局部
        {
        }
    }  
}


1、不可以被成员修饰符修饰

2、可以直接访问外部类中的成员,因为还持有外部类中的引用

但是不可以访问它所在的局部中的变量,只能访问被final修饰的局部变量

 

匿名内部类:

1、匿名内部类其实就是内部类的简写格式

2、定义匿名内部类的前提:

内部类必须继承一个类或者实现接口

3、匿名内部类的格式:

new 父类或者接口(){定义子类的内容}

4、其实匿名内部类就是一个匿名子类对象。而且这个对象有点胖。可以理解为带内容的对象

 

匿名内部类作用:简化书写,覆盖方法

 

 

 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值