第5章 抽象类、接口与类.ppt
Java教程教程第第5章章 抽象类、接口与内部类抽象类、接口与内部类n5.1 抽象类抽象类n5.2接口接口n5.3内部类内部类n5.4 包包第第5 5章章 抽象类、接口与内部类抽象类、接口与内部类5.1 5.1 抽象类抽象类(1)(1)n在继承的层次关系中,从子类到父类,类就变的更一般、更通用。类的设计应该保证父类包含子类的共同特征,也就是父类应该是子类的良好的抽象。n有时我们将一个父类设计的非常非常的抽象,以至于它都没有具体的实例,这样的类我们称之为抽象类(abstract class).n当需要一个类作为一个更通用的接口来控制一系列的相关类的时候,我就要创建一个抽象类来实现这个功能5.1 5.1 抽象类抽象类(2)(2)n抽象类:用abstract关键字来修饰一个类时,该类叫做抽象类;n抽象类必须被继承。n抽象类不能被直接实例化。它只能作为其它类的超类,这一点与最终类(final类)正好相反。n抽象方法:用abstract来修饰一个方法时,该方法叫做抽象方法。n抽象方法必须被重写n抽象方法只有声明,不能有实现。n定义了抽象方法的类必须是抽象类。nabstract returnType abstractMethod(paramlist);两个类Circle和Rectanglepublic class Rectangle public float width,height;Rectangle(float width,float height)this.width =width;this.height=height;public double area()return width*height;public class Circle public float r;Circle(float r)this.r=r;public double area()return 3.14*r*r;5.1 5.1 抽象类抽象类(3)(3)n假设有若干个Circle,以及若干个Rectangle,希望计算它们的总面积,直截了当的做法是将它们分别放到两个数组中,用两个循环,加上一个加法,这种做法是不漂亮的。n如果还有其它形状:Triangle等,上述方法显得“累赘”。我们希望有一种统一的表示,例如用一个数组shape,接受所有的形状,然后用:for(i=0;ishape.length;i+)area_total+=shapei.area();5.1 5.1 抽象类抽象类(4)(4)abstract class Shape abstract double area();class Rectangle extends Shape public float width,height;Rectangle(float w,float h)this.width =width;this.height=height;public double area()return width*height;class Circle extends Shape public float radius;Circle(float radius)this.radius=radius;public double area()return 3.14*radius*radius;5.1 5.1 抽象类抽象类(5)(5)5.1 5.1 抽象类抽象类(6)(6)通过上面的例子我们可以看出,抽象类Shape是Circle 和Rectangle的统一的接口。使利用Circle 和Rectangle的对象变的更加方便。在例子中抽象类Shape被Circle 和Rectangle继承,抽象类必须在被继承并其继承它的类不再是抽象类的时候才能被实例化,抽象方法必须被重写。5.25.2接口接口n5.2.1接口的定义与实现接口的定义与实现n5.2.2用接口实现用接口实现Java中的多重继承中的多重继承n5.2.3 接口的扩展接口的扩展n5.2.4 接口的嵌套接口的嵌套 接口(interface)就是方法定义和常量值的集合。从本质上讲,接口是一种特殊的抽象类,这种抽象类中只包含常量和方法的定义,而没有方法的实现。通过接口可以实现不相关类的相同行为,而不需要考虑这些类之间的层次关系。通过接口可以指明多个类需要实现的方法。通过接口可以了解对象的交互界面,而不需了解对象所对应的类。5.25.2接口接口 用implements子句来表示一个类使用某个接口。在类体中可以使用接口中定义的常量,而且必须实现接口中定义的所有方法。利用接口可实现多重 继承,即一个类可以实现多个接口,在implements子句中用逗号分隔。接口的作用和抽象类相似,只定义原型,不直接定义方法的内容。接口中的方法和变量必须是public的。5.2.15.2.1接口的定义与实现接口的定义与实现5.2.15.2.1接口的定义与实现接口的定义与实现Java中的接口声明的语法为:interface interfaceName/接口体 /常量域声明 域类型 域名=常量值;/抽象方法声明 返回值 方法名(参数列表);例如:interface myinterface void f();int g();5.2.15.2.1接口的定义与实现接口的定义与实现n接口实现用关键字implements,实现的具体形式:nclass ClassName implements interfaceNamen接口(interface)作为特殊形式的抽象类,和类(class)在使用上具有类似的约束。n与类继承不同,一个接口可以继承多个父接口n一个public接口只能定义在同名的.java文件中n 程序5.4 5.2.2 5.2.2 用接口实现用接口实现JavaJava中的多重继承中的多重继承n类允许实现多个接口。n 一个类可以看起来像多个接口。n类通过实现多个接口间接的实现java中的多重继承。n类可以转型为多个接口的类型进行访问。n程序5.55.2.3 5.2.3 接口的扩展接口的扩展n通过继承可以对一个或多个接口进行组合并扩展,并可以在扩展的接口中添加新的方法,使接口更加丰富。5.2.3 5.2.3 接口的扩展(例)接口的扩展(例)interface I1 void f1();interface I2 void f2();interface Ie1 extends I2 void fe1();interface Ie2 extends Ie1,I1 /只有在接口的情况下才能继承多个接口。void fe2();5.2.4 接口的嵌套接口的嵌套n类嵌套接口n接口嵌套接口5.2.4 接口的嵌套(接口的嵌套(类嵌套接口)class A interface B void method();private interface B void method();5.2.4 接口的嵌套(接口的嵌套(接口嵌套接口)interface A interface B void f();public interface C void f();5.3内部类内部类n5.3.1内部类的基本语法内部类的基本语法n5.3.2局部内部类局部内部类n5.3.3静态内部类静态内部类n5.3.4匿名内部类匿名内部类n5.3.5内部类的继承内部类的继承5.3内部类内部类n 嵌套在类里面的类就被称为内部类。内部类允许一个类定义被放到另一个类定义里。内部类是一个有用的特征,因为它们允许将逻辑上同属性的类组合到一起,并在另一个类中控制一个类的可视性。5.3.15.3.1内部类的基本语法内部类的基本语法class OuterClass class InnerClass 上面代码就是典型的内部类的代码,正如我前面说的把类InnerClass放在类OuterClass的内部 5.3.25.3.2局部内部类局部内部类n局部内部类基本的内部类形式上没什么区别,唯一不同的就是作用域不同。比如上面内部类的作用域范围是整个外层类。n 如果将这个类放在某个方法内,此时他的作用域范围只是该方法内部,那么这个方法以外是不能创建该内部类对象的。如果在某个块中,那么他的作用域范围就只在这个块以内。5.3.25.3.2局部内部类(局部内部类(2 2)publicInterfaceInnerMethod2()/创建一个局部内部类,继承自Interface接口 classInnerLocalimplementsInterface public void getInfo()System.out.println(localClass);/*在方法类创建该类的对象,并调用其方法。这个是被允许的*/Interfacelocal=newInnerLocal();local.getInfo();returnlocal;5.3.25.3.2局部内部类(局部内部类(3 3)publicInterfaceshowLocalClass(finalbooleanflag)if(flag)classInnerLocalimplementsInterface publicvoidgetInfo()System.out.println(localClass+flag);Interfacelocal=newInnerLocal();local.getInfo();returnlocal;else classInnerLocalimplementsInterface publicvoidgetInfo()System.out.println(localClass+flag);Interfacelocal=newInnerLocal();local.getInfo();returnlocal;5.3.35.3.3静态内部类静态内部类n静态内部类又被称为嵌套类,在内部类前面加上static关键字,就表示该内部类是一个静态内部类。n静态内部类是不能放在方法或者块中。n静态内部类没有了指向外层类的引用。5.3.35.3.3静态内部类(静态内部类(2 2)public class StaticInnerClass private static class InnerClass void getInfo()System.out.println(InnerClass);5.3.45.3.4匿名内部类匿名内部类n匿名内部类也是一种内部类,他区别于一般的内部类是它本身是没有任何名字的。因此被称为匿名 n使用匿名内部类能让我们的代码看起来更简洁,很好的避开耦合性。n你可以在任何创建某个对象的地方使用匿名内部类,然后重写这个类的方法来解决特定的问题。n匿名内部类是不可能有命名的构造器,这个原因也很简单,因为它本身没有名字。5.3.45.3.4匿名内部类(匿名内部类(1 1)abstract class AnonymousClass abstract public String value();public class AnonymousClassDemo public AnonymousClass makeac()return new AnonymousClass()stringstr=AnonymousClass;public String value()return str;5.3.45.3.4匿名内部类(匿名内部类(2 2)return new AnonymousClass()stringstr=AnonymousClass;public String value()return str;class MyAnonymousClass implements AnonymousClass stringstr=AnonymousClass;public String value()return str;5.3.45.3.4匿名内部类(匿名内部类(3 3)在需要参数的情况:public class AnonymousClassDemo2 public AnonymousClass makeac(int x)return new AnonymousClass(x)public int value()return super.value()*10;5.3.45.3.4匿名内部类(匿名内部类(4 4)n对内部类中定义的字段进行初始化(必须将参数设为final)public class AnonymousClassDemo3 public AnonymousClass makeac(final String str1)return new AnonymousClass()private String str=str1;public String value()return str;5.3.55.3.5内部类的继承内部类的继承n非静态内部类本身隐藏了一个指向外层类的引用。n如果我们需要一个外部类来直接继承内部类,那么这里就会产生一个问题。因为外部类并不包含这个外层类对象的引用,那么默认调用超类的构造器就会产生问题,因此连编译时都无法通过。5.3.55.3.5内部类的继承内部类的继承class OuterClass class InnerClasspublic class InheritInnerClass extends OuterClass.InnerClass /InheritInnerClass();不能被编译。public InheritInnerClass(OuterClass outer)outer.super();5.4 包包n5.4.1 创建并命名自己的包创建并命名自己的包n5.4.2 包的引用包的引用5.4 包包n提供了把相关的程序段组织成一个单元的机制,在包中定义的类必须通过他们的包名来访问。这样,包就提供了一种命名类的集合的途径。n参与了Java的访问控制机制,包中定义的类可以声明为包所私有的,使包外的代码无法访问。这样包为类提供了一种能够被封装的方式。5.4.1 5.4.1 创建并命名自己的包创建并命名自己的包n建立一个包,把你的类和接口放到里面。这需要把 package 语句放到源文件的顶部。package com.myPackage;public class TestPackage public static void main(String rgs)new Test().print();class Test public void print()System.out.println(test of using package!);5.4.1 5.4.1 创建并命名自己的包创建并命名自己的包n上面的例子把TestPackage 放到com下的myPackage包内。注意:必须把package 语句放到你所定义的类文件的第一句。npackage 语句的作用范围是整个源文件。n全世界的java程序员都在利用java编写类和接口,怎样使他们编写的相同名字的类和接口不发生冲突呢,这就是包的作用之一,我们把具有相同名字的类和接口放在不同的包下面,这样就不会发生冲突。n按照惯例,包名是创建者的Internet域名的反序,如果你按照惯例,你的package名称是独一无二的,因为你的Internet域名是独一无二的,所以也就不会出现什么名称冲突的问题了。5.4.2 5.4.2 包的引用包的引用n用成员的全称来访问它(包含路径和包名)ncom.myPackageA.A myA=new com.myPackageA.A();n导入包的成员nimport com.myPackageA.A;A myA=new A();