黑马程序员---面向对象---接口、多态、Object类、内部类

------- http://www.itheima.comjava培训、android培训期待与您交流!-------


继续接着上篇学习。。。。

四、接口
1、概述
     我们知道,抽象类中可以定义抽象方法,也可以定义非抽象方法。如果,抽象类中的方法都是抽象的,那么该类可以通过接口的形式来表示。当然,这只是接口的初期理解方法。
简单地说,接口的作用其实就是用来增强程序的扩展性。接口中定义的通常是一些事物的扩展功能,也就是说,定义的方法没有具体的方法体,那么就需要某个具体的个体来实现这个方法(即复写接口中的方法),定义自己的内容。

接口的固定写法:
      常量:public static final int NUM = 3;
      方法:public abstract void show();   //接口中的方法都是抽象方法
接口不可创建对象,因为有抽象方法,需要被子类实现,并复写接口中的抽象方法,子类才可实例化,否则子类是抽象类。
注意:
       接口可被类多实现,也就是说,一个类可以实现多个接口。
       接口与接口间可支持多继承,但方法的返回类型必须一致。
2、特点
         (1)接口是对外暴露的规则。
         (2)接口是程序的功能扩展。
         (3)接口可以用来多实现。
         (4)类与接口之间是实现刮泥,而且类可以继承一个类的同时实现多个接口。
         (5)接口与接口之间可以有继承关系。
举个简单的例子说明接口是对外暴露的规则:
比如我们使用的笔记本上有很多的USB插口、网线插口、电源插口、鼠标插口等。这些插口实际上就是接口。这些接口提供了对外使用的方式,只要符合这些插口的类型,就可以使用外接设备操作电脑:外接键盘,外接鼠标等。

举个例子用于说明接口是如何实现程序的功能扩展的(仅限于解释功能扩展这个特点):
我们知道,当我们在描述运动员时,他们不仅有属性(姓名,年龄等),还有一些行为,如训练(当然,不同的运动员训练的项目不一样,所以定义为抽象类,抽象方法,在其子类中写具体训练项目),当然,运动员不光训练,业余时间他们或许会锻炼身体或唱歌或做生意,那么这些业余项目就是运动员训练额外的功能,这时,我们就可以将这些额外的功能定义在接口中,由运动员的不同具体实例去实现。
class  InterfaceDemo
{
	public static void main(String[] args) 
	{
		BasAthlete ba = new BasAthlete();
		ba.tranning();
		ba.sing();
	}
}
interface Singing
{
	//接口名和方法名不能一样,,一样会报错
	void sing();
}
abstract class Athlete
{
	abstract void tranning();
}
class BasAthlete extends Athlete implements Singing
{
	void tranning(){
		System.out.println("我要训练棒球了");
	}
	//要用public 修饰,否则出错
    public  void sing()
	{
		System.out.println("业余唱歌");
	}
}

通过这个例子,我们看出,类中主要定义的是事物的基本功能,接口中主要定义一些扩展功能,扩展功能只有在子类具体实现的时候才能被复写并调用。

五、接口中的多态
1、概述
     多态,某种事物存在的多种体现形态。在现实世界中,多态的体现随处可见。
比如:汽车可分为很多品牌,宝马、奔驰、阿斯顿马丁等,其实这些品牌中的每辆汽车都是汽车的一个实体。
动物有很多物种,而每种物种又分为很多的实际个体,如猫、狗等。而这些个体就是动物多态的体现。
也就是说,将这些抽象的、不确定的事物当做父类(动物),把父类的子类(猫、狗)当做父类在自然界的不同体现形态。
在java语言中,多态的体现用官方语言说就是父类的引用指向了自己的子类对象。
也就是说,动物(Animal)可以指向自己的子类对象(猫)。
2、转型
转型可以分为向上转型(类型提升)和向下转型。
比如,猫是动物的一种,那么,猫转型为动物就称为向上转型;而动物转型为猫就是向下转型,也就是说,动物可以
3、多态中成员函数的特点
简单的说就是父类引用指向了子类对象。
在编译时期,参阅引用型。判断所属的类中是否有调用的方法,若有,编译通过,若没有,编译失败。
在运行时期,参阅对象所属的类中是否有调用方法。
结论:编译看左边,运行看右边。
成员变量的特点:无论编译或运行,都参照左边(引用型变量所有的类)。
4、多态的主板示例
     我们知道,电脑可以上网,听歌,玩游戏等等(网卡、声卡等),那么,这些是怎样实现的呢?我们可以定义一个类,并定义一些方法用于上网,听歌(调用这些方法)。但是,如果以后电脑升级,又有很多的功能,我们还要定义一些类、方法,这样会很麻烦,所以,要编写具有扩展功能的代码,以便以后复写就可以。
     我们知道(作为了解),主板(主机板、系统板、木板)安装在机箱内,他是微机最基本的也是最重要的部件之一。主板上主要安装的是计算机的主要电路系统,一般有BIOS芯片、I/O控制芯片、键盘和面板控制开关接口、指示灯插接件、扩充插槽、主板及插卡的直流电源供电接插件等元件(百度的)。

简单的说,我们要使用主板上的元件就必须要通过机箱连接并加以通电才能使计算机运行起来。而主板上的那些扩充插槽等就相当于对外暴露的规则(接口),只要符合这个规则就可以使用主板的功能。
所以,我们定义一个接口,对外提供一些方式用于访问主板上的一些功能。

//定义一个PCI接口   
//PCI是一种连接电子计算机主板和外部设备的总线标准 或是安装在插槽上的扩展卡。
interface PCI {
                   //定义抽象方法,因为明确哪些设备使用
                  public void open();
                  public void close();
}
//定义主板类,
class MainBoard{
                 //定义主板的运行方法(在这里简单定义)
                public void run(){
                    System.out.println("mainboard run");
}
//因为主板要连接PCI,外接设备才能发挥作用
public void usePCI(PCI P){  //这里使用了多态的性质:接口型引用指向了自己的子类对象
                                       //PCI p  = new NetCard();
                                       //PCI p  = new SoundCard(); 
             //当没有外接设备时,运行时会出现空指针异常
             if (p!=null)
             //若不为空,则外接设备可以使用
              p.open();
              p.close();
}
}
//定义PCI的子类,并实现PCI,
class NetCard implements PCI{
             //复写父类方法
            public void open(){
              System.out.println("netcard open");
}
         public void close(){
          System.out.println("netcard close");
}
}
//定义PCI的子类,并实现PCI,
class SoundCard implements PCI{
            //复写父类方法
            public void open(){
               System.out.println("SoundCard open");
}
           public void close(){
                System.out.println("SoundCard close");
}
}

main函数中:
MainBoard mb = new MainBoard();
mb.run();
//mb.usePCI(null);
mb.usePCI(new NetCard ());
mb.usePCI(new SoundCard ());
从上面的例子可以看出,无论一年后或者若干年后再有新的外接设备出现,只要符合PCI规则就可以使用,从而减少了代码的臃肿,增强了程序的功能扩展。

六、Object类
      Object类是类层次结构的根类(也就是说是所有类的父类)。我们知道,在定义一个类Person时,不写构造函数,其默认会有一个隐士的无参的构造函数,也就是Person(){super();} 在这里,super所指向的就是Object()这个构造函数。
      所以说,Object是所有对象的直接或间接父类,那么,Object类中定义了所有对象都具有的功能。只要类已存在,就已经具有了Object类中的所有方法。
      但是,有时,我们不想使用父类(Object)中的默认方法,想定义自己特有的内容,这时,我们就可以沿袭父类中的功能,改变父类中的默认内容(写自己的特有内容),也就是复写(覆盖)父类的方法。

举个例子吧,Object类中    boolean equals(Object obj)
我们知道,java认为,所有对象都具有比较性(只要是实体),都可以判断一个对象和另一个对象是否"相等"。
判断两个对象是否相等,用我们以前的思路,我们可以定义一个比较方法,用于实现这个功能,但父类中已经定义了这样的方法,我们拿过来用就可以了,当然要编写自己的比较方式(也就是复写父类方法)。
看一个示例:
class ObjectDemo 
{
	public static void main(String[] args) 
	{
		Person p1 = new Person();
		Person p2 = new Person();

		System.out.println(p1.equals(p2));
	}
}
class Person
{
	public boolean equals(Object obj)
	{
		//判断传入的对象是否是Person类型的,
		if (!(obj instanceof Person))
	      {
			//若不是,返回false(或抛出异常)
			return false;
		  }
		//若是,将Person强转成obj类型
		Person p = (Person)obj;
		return true;		
	}
}

在这里,用到了多态的性质。当父类引用指向了自己的子类对象的时候,
public boolean equals(Object obj)  //这里 就相当于 Object obj = new Person();

七、内部类
      内部类(嵌套类)就是类中有类,但类中的类必须与外类有关系。
1、内部类访问规则
     内部类可直接访问外部类中的成员(包括私有):外部类名.this.外部类成员
     外部类要访问内部类,要建立内部类对象:Outer.Inner in = new Outer().new Inner();
2、静态内部类
    只能直接访问外部类中的static成员。
3、内部类定义规则
    但类中的类必须与外类有关系
4、匿名内部类
内部类要定义在成员的位置上,无对象,不运行
内部类要定义在局部(要创建对象,不可被成员修饰符修饰,可访问被final修饰的局部变量)
匿名内部类:
(1)匿名内部类是内部类的简写格式
(2)定义匿名内部类的前提:
    内部类必须是继承一个外部类或实现接口
(3)匿名内部类书写格式:
    new 父类或接口( ){定义子类内容}
(4)匿名内部类就是子类对象(带内容的对象)。
(5)匿名内部类中的方法最好不要超过3个。
写个小例子:
abstract Demo{
           abstract void show();
}
class Outer{
             int x = 3;
/*
//创建内部类,并继承Demo
class Inner extends Demo{
void show (){
System.out.println("show::"+x);
}
}
*/
public void function(){
//new Inner().show();  外部类调用内部类方法:创建内部类对象,调用方法
/*
注释的部分可以简写成匿名内部类。
匿名内部类,顾名思义就是没有类名的内部类。
内部类没有类名那怎么调用方法呢?
new Inner().show();  我们可以分析一下,这句里的内部类类名Inner没有了,因为Inner继承了Demo,那么,可以创建Demo的子类对象来调用内部类方法,即沿袭父类的功能,来建立自己的特有内容,也就是覆盖父类的show方法,
*/
new Demo(){ 
//一下则是父类Demo的子类对象
void show(){
System.out.println("x=="+x);
}
}.show();  //Demo的子类对象调用show方法。
}
}

呃,在这里只是初步对匿名内部类有了一些了解,在以后的学习中还要继续留心,将匿名内部类掌握熟练。。。。。



---------- http://www.itheima.comjava培训、android培训期待与您交流!期待与您交流! ----------

你可能感兴趣的:(java)