当前位置:文档之家› 第5章 继承和多态

第5章 继承和多态

第5章  继承和多态
第5章  继承和多态

第5章继承和多态

继承和多态性是面向对象程序设计的重要内容。继承机制是实现软件构件复用的一种强有力的手段。多态性是面向对象编程的重要特性,是继承产生的结果。Java语言很好的体现了继承和多态性两大特性。本章将讨论用Java语言实现继承和多态性,具体将介绍继承概念、继承的实现、抽象类的作用、方法的覆盖以及用接口实现多继承。

5.1继承

继承是面向对象程序设计的三大概念之一,是面向对象程序的重要概念,它使程序代码复用成为可能。假设已经定义和实现类DigitalProduction(代表数码产品),需要定义一个新的应用类MobilePhone(代表手机)。由于手机是数码产品的一种,所以没有必要对类DigitalProduction中属于数码产品特征重新书写代码,只需要继承类DigitalProduction的属性特征即可。这样,类MobilePhone通过继承获得了类DigitalProduction的数据和方法。由于类MobilePhone也具有自身的特征,如“进网许可号”,可以为这些异于其他数码产品的特征定义成员数据和成员方法。这样,MobilePhone继承于DigitalProduction,又具有新的属性特征。图5-1可以表示了两个类之间的继承关系。

图5-1 MobilePhone继承DigitalProduction

从这个意义上来说,继承是指一个新的类继承原有类的基本特性,并增加新的特性。通俗地说,新的类与原有类之间体现了一种“is-a”关系。只要类和类之间存在的继承关系,这种扩展可以一直延续下去,它体现出类的层次结构。例如,而类MobilePhone继承于类DigitalProduction。而类IntelligentMobile(代表智能手机)继承于类MobilePhone。

继承可以分成两大类型:单继承和多继承。单继承是一个类只能从一个类派生而来,即只有一个父类。多继承是一个类可以从多个类派生而来,可以有多个父类。Java语言只支持单继承,不支持多继承。

5.1.1 父类和子类

Java语言中,继承实际上是一个类扩展一个已有的类。被扩展的类是父类,而扩展类是子类。子类继承了父类的类成员,并可以定义自己的独特的属性成员。通常体现了子类和父类之间是派生与被派生的关系。所以,有时称父类为基类,而子类称为派生类。

Java语言也体现出类的层次结构。Java语言中定义类https://www.doczj.com/doc/d14124205.html,ng.Object,它是所有类的父类。其他类无论是直接还是间接都是继承了Object类,具有Object类的属性,如在第4章中说明的finalize()方法。比如,Java语言提供的类https://www.doczj.com/doc/d14124205.html,ng.String直接继承于类https://www.doczj.com/doc/d14124205.html,ng.Object,而javax.swing.JOptionPane则是间接继承于https://www.doczj.com/doc/d14124205.html,ng.Object,JOptionPane类具体继承情况见图5-2。同样,用户自定义类也是直接或间接继承于https://www.doczj.com/doc/d14124205.html,ng.Object类,具体实现见5.1.2。

图5-2 javax.swing.JOptionPane的继承示意

5.1.2 继承的实现

Java语言中是通过关键字extends来实现单继承的。简单的实现格式如下:class 子类名extends 父类名{

类体

}

有一点要注意,如果在格式中没有通过extends关键字来标明父类名,这并不是意味着该类无父类,相反,它表示该类是https://www.doczj.com/doc/d14124205.html,ng.Object的子类。

例5.1 类继承的示例。

public class BaseClass{ //定义一个类BaseClass

public int intValue; //定义成员数据intValue;

public BaseClass(){

intValue=3;

System.out.println("Base Class 定义");

}

public void showBaseMessage(){

System.out.println("Base Class 信息");

}

}

public class DerivedClass extends BaseClass{//定义类DerivedClass

public DerivedClass(){

System.out.println("Derived Class 定义");

}

public void showDerivedMessage(){

System.out.println("继承而来的数据:"+intValue);//引用继承的成员数据intValue

System.out.println("Derived Class 信息");

}

public static void main(String args[]){

DerivedClass dc=new DerivedClass();

dc.showBaseMessage();//引用继承的成员方法showBaseMessage

dc.showDerivedMessage();

System.exit(0);

}

}

图5-3 例5.1的运行结果

例5.1定义了两个类BaseClass和DerivedClass,其中DerivedClass是BaseClass的子类,BaseClass是DerivedClass的父类。它们之间通过定义DerivedClass中增加extends子句来实现继承关系。尽管类BaseClass的定义没有用关键字extends来说明父类,但实际上它是隐性

的定义为https://www.doczj.com/doc/d14124205.html,ng.Object的子类。这样,https://www.doczj.com/doc/d14124205.html,ng.Object、BaseClass和DerivedClass之间就构成了继承关系链。创建一个子类如DerivedClass的对象时,会从上向下调用Object-BaseClass-DerivedClass继承链的默认构造方法。从图5-3中可以看出,创建一个DerivedClass的对象之前先调用了父类BaseClass的默认构造方法。注意,如果在继承链中存在某个父类没有定义默认构造方法,会产生编译错误。

不过,尽管子类可以继承父类的成员数据和成员方法,但并不意味着子类可以完全继承父类的全部属性。如果将例5.1中类BaseClass的公有(public)成员数据intV alue改成私有(private)成员数据,再编译类Derived,会发现程序出现编译错误。这是由于类成员的访问控制限制了类成员的可见性。父类的私有成员是不能被子类所继承。就好比孩子继承了父亲的部分特征,而不是全部特征。

5.2抽象类

在现实生活中,可以发现这样的现象:许多实物抽象出成为一个共同的类别,如“交通工具”,但是“交通工具”并直接对应着实际存在的类别如卡车、自行车、三轮车等。又如“动物”,并不特指具体的某个实际存在,它只是哺乳动物、两栖动物等以有机物为食物,可运动生物的统称。“交通工具”、“动物”等这些只是作为一个抽象概念存在,对一组固定实现的抽象描述,并不对应具体的概念。因此,在面向对象程序设计中,可以将这些抽象描述定义为抽象类,而这一组任意个可能的具体实现则表现为所有可能的派生类。由于抽象类对一组具体实现的抽象性描述,所以抽象体是不能修改的。通常抽象类不具备实际功能,只用来派生子类。

5.2.1 抽象方法

Java语言中,用关键字abstract修饰的方法为抽象方法。语法格式形如:

abstract 返回值类型方法名([形式参数]);

例如:abstract void showMessage();

抽象方法只有方法头没有方法体,即只提供方法的规格说明,没有具体的实现。抽象方法只能出现在抽象类(见5.2.2)和接口(见5.4)中,其他类中定义会产生编译错误。有两点必须注意:

1)final关键字不能修饰抽象方法。这是因为final是不可修改的方法是最终的方法,而抽象方法没有方法体,能被派生类进行覆盖;

2)static是不能修饰抽象方法的。静态方法占据固定内存空间,而抽象方法根本就不可能运行,不会加载到内存中。所以,static关键字不能修饰抽象方法。

5.2.2 抽象类

抽象类是用关键字abstract修饰的类为抽象类。语法格式形如:

abstract class 抽象类名{

类体

}

抽象类只是具体实体的抽象描述,是不可以实例化对象。尽管抽象类定义构造方法是没有语法错误,但是没有实际意义。抽象类中可以定义非抽象方法,也可以定义抽象方法。抽象方法在它的派生子类中可以覆盖,来实现具体功能。抽象类派生出的子类,必须对抽象类中的抽象方法重写。如果没有对抽象方法重写,该子类须定义为抽象类,否则产生编译错误。

3

与抽象方法类似,如果一个类要定义为抽象类,就不能用关键字static或关键字final修饰,原因同抽象方法,在这里就不再说明。

例5.2 抽象类的示例。

public abstract class AbstractClassExample{ //AbstractClassExample.java

public abstract void showMessage(); //定义抽象方法showMessage()

public void printClassName(String name){//定义非抽象方法printClassName(String)

System.out.println(name);

}

}

public class DerivedAbstractClass extends AbstractClassExample{//DerivedAbstractClass.java public DerivedAbstractClass(){

System.out.println("Derived Abstract Class Definition");

}

public void showMessage(){ //覆盖父类的showMessage()方法;

System.out.println("Derived Abstract Class Message");

}

public static void main(String args[]){

DerivedAbstractClass dac=new DerivedAbstractClass();

dac.showMessage();

dac.printClassName("Class name is: DerivedAbstractClass");//引用继承来的方法

System.exit(0);

}

}

图5-4 例5.2的运行结果

5.3多态性

多态性是面向对象程序设计的重要特性,它是继承机制产生的结果。所以,继承是多态的前提。面向对象程序设计中,严格的来说多态性是运行绑定机制。这种机制是实现将方法名绑定到方法具体实现代码。通俗地理解就是“一个名字,多种形式”。实际上,最常见的多态的是符号“+”,有如下的表示式:

6+5 //实现整数相加

3+5.0f //将3隐性转化为float类型,实现单精度数字的相加

"IAMCHINESE"+4 //实现字符串连接操作。

同一个“+”有多种含义:整数相加、单精度数字相加、双精度数字相加、字符串连接等操作。当然,上述的表达式3+5.0f中数据类型的隐性的转换也是一种多态的体现。又如,在第三章讨论的对象的finalize()方法也是多态。因为,不同类型的对象都有finalize()方法,但根据要求的不同,可以赋予finalize()方法不同代码内容,产生不同的功能。另外,类的构造方法也是多态的一种形式。在创建对象时,根据参数的性质来选择构造方法初始化对象。

根据消息选择响应方法的角度来看,多态分成两种形式:编译多态(Compile-time Polymorphism)和运行多态(Run-time Polymorphism)。在编译时期根据信息选择响应的方法称为编译多态。Java语言中,实现编译多态性主要有方法的重载。运行的多态是在程序运行

的时才可以确认响应的方法。通常运行的多态是通过继承机制引起的。

从实际编程的角度来看,Java语言实现多态性有三种形式:1)方法的重载;2)通过继承机制而产生的方法覆盖;3)通过接口实现的方法覆盖(见5.4.2)。在本节中对方法的重载和方法的覆盖做一个详细的介绍。

5.3.1 方法的重载

重载(Overloading)实质上就是在一个类内用一个标识符定义不同的方法或符号运算的方法名或符号名。Java语言中支持符号的重载,如前提及的运算符“+”。不过Java语言中不支持用户自定义的符号重载,可以支持用户定义方法的重载。

方法的重载具体可以理解为,同一个方法名对应不同的方法定义。这些方法的格式说明中的参数不同,即,具体涉及到参数的类型、参数的个数是有所不同的。值得注意的是,在Java语言中,方法的返回值和方法的访问控制不作为区分方法的一个因素。请看下列的方法定义格式:

①public void showMessage()

②public void showMessage(int x)//与○1不同的参数

③public void showMessage(int y)// 与○2不同的参数名

④private void showMessage()//与○1不同的访问控制

⑤public int showMessage()//与○1不同的返回值类型

在这些表达式中方法定义①和方法定义②是可以视为方法的重载。方法定义○1和方法定义○4和方法定义○5不是方法的重载。在编译时会将方法定义○1、方法定义○4和方法定义○5作为同一种方法,如果这三种形式的showMessage()方法放在同一个类中,会产生编译错误。尽管方法定义○2和方法定义○3具有不同的参数名,但二者是同一个方法定义,不能视之为重载,因为参数个数和参数类型相同。

例5.3 Java中方法重载的示例。

public class OverloadingExample{

public OverloadingExample(){ //无参构造方法

System.out.println("方法重载示例:无参构造方法");

}

public OverloadingExample(String string){//有参构造方法

System.out.println("方法重载示例:有参构造方法,参数:"+string);

}

public void showMessage(){

System.out.println("方法重载的信息显示");

}

public void showMessage(String string){

System.out.println("显示字符串:"+string);

}

public void showMessage(int intValue){

System.out.println("显示整数:"+intValue);

}

public void showMessage(String string,int intValue){

System.out.println("显示字符串:"+string);

System.out.println("显示整数:"+intValue);

}

public static void main(String args[]){

OverloadingExample ole1=new OverloadingExample();

OverloadingExample ole2=new OverloadingExample("对象2");

5

ole1.showMessage(1);

ole1.showMessage("对象1");

ole2.showMessage();

ole2.showMessage("对象2");

System.exit(0);

}

}

图5-5 例5.3的运行结果

例5.3中,构造方法OverloadingExample()是重载,因为它有两种形式:有参和无参。在主方法main()中,根据实参情况不同,由编译器分别调用无参的构造方法和有参的构造方法,创建的对象ole1和ole2。对象ole1和对象ole2调用成员方法showMessage()是重载的,根据调用的实际参数的类型,编译器自动加载不同的showMessage()方法形式。例如,运行ole1对象的showMessage(1),编译器将showMessage名绑定到方法showMessage(int)定义的代码中,具体的运行结果观察图5-5。在下面通过一个实际问题来讨论重载。

例5.4 定义一个类Counter,具有实现求绝对值运算的功能。

public class Counter{

public Counter(){

System.out.println("求绝对值");

}

public int abs(int x){ //整数求绝对值

return x>=0?x:-x;

}

public long abs(long x){ //长整数求绝对值

return x>=0?x:-x;

}

public float abs(float x){ //单精度求绝对值

return x>=0?x:-x;

}

public double abs(double x){ //双精度求绝对值

return x>=0?x:-x;

}

public static void main(String args[]){

Counter c=new Counter();

System.out.println("-30.445的绝对值="+c.abs(-30.445));

System.out.println("-30的绝对值="+c.abs(-30));

System.exit(0);

}

}

图5-6 例5.4的运行结果

5.3.2 方法的覆盖和隐藏

方法的覆盖(Overriding)实质是指子类具有重新定义父类成员方法的能力。这种重新定义表示子类定义的方法具有和父类的方法同名称、同参数类型、同参数个数、以及同返回值。方法格式定义尽管相同,但具有不同的方法体,实现的内容根据程序员的要求而有所不同。子类的方法覆盖父类的同名方法。这意味着,子类对象的实例方法调用只会调用子类中定义的方法,而不是父类中同格式说明的方法。

从第4章介绍可以知道,类的静态方法是一种类方法,对该类的所有对象是共享的。有一种特殊的情况,就是子类覆盖了父类内定义的静态方法。这时,父类的静态方法被隐藏起来了,在子类中失去作用。要求子类定义的方法必须和父类的静态方法具有相同性质和相同的方法格式说明。即,同为静态类型、同方法名、同方法参数类型、同方法参数个数、同返回值。如果子类定义的方法在重新定义父类的静态方法时,没有用关键字static定义,则会产生错误。因为,用一句话可以概括成:如果子类的方法覆盖父类的静态方法,则父类的方法在子类中隐藏起来了。为了说明覆盖的定义,请看例5.5。

例5.5 方法覆盖和隐藏的示例。

public class ParentClass{ //ParentClass.java

public static String getMessage(){ //ParentClass类方法getMessage();

return "获取ParentClass类的对象的信息";

}

public void showMessage(String message){ //被ChildClass的showMessage()方法隐藏

System.out.println("输出ParentClass类的对象的信息:"+message);

}

}

public class ChildClass extends ParentClass{ //ChildClass.java

public static String getMessage(){ //定义ChildClass类方法getMessage();

return "获取ChildClass类的对象的信息";

}

public void showMessage(String message){ //覆盖了ParentClass的showMessage()方法。

System.out.println("输出ChildClass类的对象的信息:"+message);

}

}

public class OverridingTest{ //定义测试类OverridingTest

public static void main(String args[]){

ParentClass cc=new ChildClass(); //对象变量cc引用ChildClass的对象

System.out.println("输出一个对象");

cc.showMessage("Writen by Chen"); //调用对象cc的方法showMessage()

System.out.println(cc.getMessage()); //输出对象cc的获取信息

System.out.println("输出另外一个对象");

cc=new ParentClass(); //对象变量cc引用ParentClass类的对象

cc.showMessage("Writen by Chen");

System.out.println(cc.getMessage());

System.out.println("再输出一个ChildClass的对象");

ChildClass cc2=new ChildClass(); //创建对象cc2

cc2.showMessage("Writen by Chen");

System.out.println(cc2.getMessage());

System.exit(0);

}

}

7

图5-7 图5.5的运行结果

从图5-7中显示的运行结果可以观察到两方面的内容。首先,子类ChildClass的showMessage()方法覆盖了父类ParentClass的同名方法。在子类ChildClass中定义getMessage()覆盖了父类的类方法getMessage(),而父类的类方法getMessage()在子类中隐藏,没有发挥作用。如果在子类定义方法getMesssage()中没有用关键字static修饰,这时会产生编译错误。其次,在上例中,对象变量cc声明为ParentClass的对象,但是该对象变量即可引用ParentClass 的对象,也可以引用ChildClass对象。具体引用对象的类型,取决于在运行期间该对象变量引用的对象的类型,这就是运行时的多态。

子类覆盖父类的方法,访问控制可以不同。但是,子类的访问控制的访问权限不能低于父类的同名方法访问权限。否则,会产生编译错误。例如,将例5.5中的ParentClass.java和ChildClass.java改成如下形式:

public class ParentClass{

public static String getMessage(){

return "Hello, Parent Class";

}

protected void showMessage(String message){ //保护类型

System.out.println("Parent Class Message "+message);

}

}

public class ChildClass extends ParentClass{

private static String getMessage(){ //定义私有类型,出现编译错误,要修改成public则正确。

return "Hello Child Class";

}

public void showMessage(String message){//正确

System.out.println("Child Class Message "+message);

}

}

从编译上述程序,子类覆盖父类方法protected static String getMessage(),出现编译错误,要修改成protected或public则正确。

5.3.3 数据成员的隐藏

父类的数据成员可以在子类中隐藏,只要子类中定义了同名的数据成员。即使数据成员的类型不同,也视为父类的数据成员被隐藏了。如果要在子类中引用父类的同名数据成员,只能通过关键字super(见5.3.4)来实现。

例5.6 数据成员隐藏的示例。

public class ParentClass{ //ParentClass.java

public String string; //定义string为String

public ParentClass(){

string="Parent Class";

9

System.out.println("Parent Class Definition: "+string); } protected static String getMessage(){ return "Hello, Parent Class"; }

protected void showMessage(String message){ System.out.println("Parent Class Message "+message); } }

public class ChildClass extends ParentClass{ //ChildClass.java public int string; //定义string 为int

public ChildClass(){ string=0; System.out.println("Child Class Definition: "+string);

}

protected static String getMessage(){ return "Hello Child Class"; }

public void showMessage(String message){ System.out.println("Child Class Message "+message); } }

public class OverridingTest{ //OverridingTest.java public static void main(String args[]){ ChildClass cc=new ChildClass(); cc.showMessage("Writen by Chen"); System.out.println(cc.getMessage()); System.exit(0); }

}

图5-8例5.6的运行结果

5.3.4 super 关键字

super 关键字表示对类的父类的引用。在子类中有时会使用父类的数据和方法,这时就可以利用super 关键字来实现对父类的引用。super 关键字不是一个对象的引用,而是调用父类的成员特有的关键字。super 关键字主要应用在两个方面:1)应用于引用父类的构造方法;2)应用于引用父类中被子类覆盖的成员方法和隐藏数据成员。

例5.7 super 关键字的示例。

public class SuperClass{ //SuperClass.java private String string; private int intValue; public SuperClass(){ //构造方法 string="Super Class";

intValue=1;

}

public void setIntValue(int x){

intValue=x;

}

public void setStringValue(String string){

this.string=string;

}

public int getIntValue(){

return intValue;

}

public String getStringValue(){

return string;

}

public void showMessage(){

System.out.println("父类的信息有:"+string+","+intValue);

}

}

public class SubClass extends SuperClass{ //SubClass.java

public String string;

public int intValue;

public char subChar;

public SubClass(){

super(); //引用父类的构造方法

subChar='C';

}

public void setChar(char c){

subChar=c;

}

public char getChar(){

return subChar;

}

public void showMessage(){

super.showMessage(); //引用父类的被覆盖的方法showMessage()

System.out.println("子类增加信息:"+subChar);

}

}

public class SuperTest{ //SuperTest.java

public static void main(String args[]){

SubClass sc=new SubClass(); //创建对象sc

sc.showMessage(); //调用方法showMessage()

System.exit(0);

}

}

图5-9 例5.7的运行结果

值得注意的是,父类的私有数据成员不能通过super关键字来访问。因为父类的私有数据成员的作用域只在定义类中有效。所以,在SubClass.java中试图通过super.string来访问父类定义的数据string,会产生编译错误。

另外,不能通过super关键字在子类对象中引用父类静态成员。因为,类定义的静态成员方法和静态数据成员被加载后会占据固定的存储空间,对所有类的对象有效。子类静态成员占据的空间与父类静态成员占据的空间没有关系。如果在子类引用父类的静态类方法和静态数据成员会产生编译错误。把例5.7改写成如下形式后SubClass.java会出现编译错误。

public class SuperClass{

private static String string; //定义静态数据string

private static int intValue; //定义静态数据int

public SuperClass(){

string="Super Class";

intValue=1;

}

public void setIntValue(int x){

intValue=x;

}

public void setStringValue(String string){

this.string=string;

}

public int getIntValue(){

return intValue;

}

public String getStringValue(){

return string;

}

public static void showMessage(){ //定义静态成员方法

System.out.println("父类的信息有:"+string+","+intValue);

}

}

public class SubClass extends SuperClass{

public static String string;

public static int intValue;

public char subChar;

public SubClass(){

super();

subChar='C';

}

public void setChar(char c){

subChar=c;

}

public char getChar(){

return subChar;

}

public static void showMessage(){

super.showMessage(); //编译错误

System.out.println("子类增加信息:"+subChar);

}

}

5.4接口

Java语言不支持多继承,但是在有的情况下需要使用多继承。比如大学的人员分成学生和在校的职工。如果某些在校职工正在读本校的在职研究生,这时他们就具有在校职工和学生两种身份。用UML简图来表示,如图5-10所示,其中,用Person表示人,用Student表示学生,用Employee表示职工,用EmployedStudent表示在读的本校职工。在现实生活中类似的多继承的例子随处可见。

11

图5-10 UML简图表示多继承

可是,多继承的存在有可能导致“二义性问题”。假设Person类具有某个公共方法如setName(),那么类Employee和类Student都继承了该公共方法,在这两个类中通过覆盖可以重写该方法setName(),当在类EmployedStudent的对象中调用实例方法setName()时,将无法判别调用的是从类Employee继承而来的方法,还是从类Student中继承的方法,具体的调用完全取决于运行状态。这种“二义性问题”会导致用户对程序代码的错误的理解。Java语言可以通过接口概念,一方面实现多继承,同时避免“二义性问题”的产生,另一方面为Java 语言在支持单继承机制的前提下实现多态提供了方便。

所谓的接口(Interface)实质上就是为外界提供运算,而不揭示这些运算的结构或具体的实现内容。从编程的角度看,Java语言定义的接口实际上是一组抽象方法和常量的集合,为其他类提供运算的外部说明。接口为一个或多个类提供一个行为规范,具体的实现在这些类中完成,这些类之间并不存在层次关系。通过接口可以了解对象的实例方法的原型,而不需要了解这些方法的具体实现。接口的存在有效解决了如何实现多继承,同时避免了由于多继承产生的“二义性问题”。

5.4.1 接口的格式定义

Java语言中,接口是通过关键字interface来实现定义的,具体格式如下:

[public] interface 接口名[extends 父接口名表]{

接口体

}

接口名的定义规则同类名的规则。接口名可以由多个单词组成,每个单词的首字母为大写。接口可以有继承关系,通过关键字extends实现继承。接口体中定义的是方法和常量。接口体中定义的所有方法不管是否用来显式的定义为公共的抽象性质(public abstract),还是缺省性质定义,所有方法隐含为公共的(public)和抽象(abstract)的,方法体为空。接口体中定义的常量格式如下:

[final] [static]数据类型常量标识符=常量值;

例5.8 接口的示例。

//Movable.java

interface Movable{ //定义接口Movable

public abstract void move();

}

//Drawable.java

interface Drawable{ //定义接口Drawable

public abstract void draw();

13

}

//Shapable.java

interface Shapable extends Movable,Drawable{ //继承了Movable 和Drawable 接口; public abstract void run(); }

在例5.8中定义了三个接口:Movable 、Drawable 和Shapable ,接口Shapable 继承了接口Movable 和接口Drawable ,这意味着接口Shapable 继承接口Movable 的抽象方法move ()和继承了接口Drawable 的抽象方法draw ()。

5.4.2 接口的实现

Java 语言中通过关键字implements 来实现接口,具体的实现是通过类来完成的。接口实现的具体格式如下:

class 类名 implements 接口名表{ 类体

}

接口的定义类似于抽象类,但是它的实现是依赖于类,不是通过继承来实现的。在实现的类中,对接口中定义的所有方法进行覆盖,根据具体要求进行定义。如果没有对所有方法覆盖,会导致实现接口的类编译错误,或必须定义该类为抽象类。

例5.9 定义一个长方形的类RectangleShape 实现例5.8定义的接口Movable 和Drawable

的示例。

public class RectangleShape implements Movable,Drawable{ public void move(){

System.out.println("Rectangle Move"); }

public void draw(){

System.out.println("Draw a Rectangle"); }

public static void main(String args[]){

RectangleShape rs=new RectangleShape(); rs.move(); rs.draw();

System.exit(0); }

}

图5-11 例5.9的运行结果

例5.10 定义一个立方体的类CubeShape 实现例5.8定义的接口Movable 和Drawable 的

示例。

public class CubeShape extends RectangleShape { //CubeShape.java public void move(){

System.out.println("Cube Move"); }

public void draw(){

System.out.println("Draw a Cube"); }

public static void main(String args[]){

RectangleShape cs=new CubeShape(); //定义对象变量cs,引用CubeShape对象

cs.move();

cs.draw();

System.exit(0);

}

}

图5-12 例5.10的运行结果

例5.9和例5.10定义的类CubeShape是类RectangleShape的子类,所以也实现了接口Movable和接口Drawable。对这两个接口中的方法move()和方法draw()进行覆盖,使得类RectangleShape和类CubeShape的对象对同一种方法名具有不同的实现内容。在例5.10中,一个RectangleShape对象变量cs可以引用RectangleShape对象,也可以引用CubeShape对象,其中实现对象接口的方法的调用取决于在程序运行期绑定的方法,这就是运行多态性的另外一种形式。在该例中,对象变量cs引用的是CubeShape的对象,最后调用的是CubeShape 中实现接口的move()和draw()方法。

接口作为一种特殊形式的类,它也可以作为数据类型存在,其作用和类作为数据类型是一样的。当接口作为一种数据类型时,定义的接口类型的引用变量可以接受任何一个实现接口的类的对象。为了说明问题,请看例5.11。

例5.11接口作为数据类型的示例。

public interface Workable{//定义接口Workable

public abstract void workModel(); //定义方法workModel()

}

public abstract class Person implements Workable{ //定义抽象类Person

public abstract void workModel();

}

public class Student extends Person{ //定义类Person的子类Student

public void workModel(){

System.out.println("学生的任务是学习");

}

}

public class Teacher extends Person{ //定义类Person的子类Teacher

public void workModel(){

System.out.println("教师的任务是教学");

}

}

public class Task{ //定义类Task

public static void showMessage(Workable subject){//接口Workable作为方法的参数类型

subject.workModel();

}

}

public class TestTask{

public static void main(String args[]){

Student student=new Student();

15

Teacher teacher=new Teacher(); Task.showMessage(student); Task.showMessage(teacher);

}

}

图5-13 例5.11的运行结果

例5.11中,类Student 和类Teacher 继承类Person ,由于抽象类Person 要实现接口Workable ,导致类Student 和类Teacher 也实现了接口,并对接口定义的方法workModel()覆盖。在类Task 中,定义的静态方法showMessage()中以接口Workable 作为形式参数类型定义一个变量。此时,当类Task 的静态方法showMessage()被调用的时候,方法会接受实现Workable 接口类的对象来作为实际参数,如类Teacher 对象teacher 和类Student 的对象student 。从例5.11中可以看到,接口作为数据类型,无论实现接口的类型性质如何,在一定程度上提高了多继承。

5.5 本章小结

Java 是一个面向对象程序设计语言,具有封装性、继承性和多态性。继承是体现了类定义的扩展,有效的支持了代码复用,充分表现了面向对象程序设计的灵活、便利性。本章详细的介绍了用Java 语言实现继承。并对用于派生子类的抽象类做了一个说明。

多态性简单的可以理解为“一个接口,多种实现”。为了实现多态性,Java 语言定义重载、覆盖、隐藏等概念,通过它们来实现多态。多态性从编程的角度而言,有方法的重载、方法的覆盖、类型的隐性转换等。由于运行多态往往是通过覆盖来体现,有两种方法可以实现运行多态:一种是利用继承机制来实现多态,另外一种是利用接口实现多态。

接口实质是一组方法和常量的集合。Java 语言利用关键字interface 来定义,在类中用implements 来实现接口,对接口说明的抽象方法进行覆盖。接口解决了Java 语言不能实现多继承的问题。更为理想的是,通过接口有效的克服其他语言在实现多继承中导致的“二义性问题”。

习 题 五

1.子类将继承父类所有的属性和方法吗?为什么?在什么情况下会出现子类对父类变量的隐藏?什么情况下出现子类对父类方法的覆盖?试举一例。

2.方法的覆盖和方法的重载有什么不同?

3.接口是什么?它将起到何种作用?如何定义接口?如何使用接口?假设复数类实现了一个四则运算的接口,试编程建立并使用这个接口。 4.计算 式1:y = x + x/2 + x/3 + … + x/n; 式2:y = x + x/2! + x/3! + … + x/n!;

要求:①x 为实数,n 为正整数。②任意输入当n 为奇数时,按照式1计算,当n 为偶数时,按照式2计算。③利用继承机制编程。 5.编程通过继承线性表实现栈数据结构及其操作。 6.利用接口编写计算三角形、梯形面积及周长的程序。

继承与多态习题

继承与多态习题 一.基本概念与基础知识自测题 8.1填空题 8.1.1 如果类α继承了类β,则类α称为(1)类,而类β称为(2)类。(3)类 的对象可作为(4)类的对象处理,反过来不行,因为(5)。如果强制转换则要注意(6)。 答案:(1)基类 (2)派生类 (3)派生类 (4)基类 (5)派生类有一些新成员 (6)只能派生类强制转换为基类 8.1.2 当用public继承从基类派生一个类时,基类的public成员成为派生类的(1)成员, protected成员成为派生类的(2)成员,对private成员是(3)。公有派生可以使其类的(4),所以公有派生是主流。 答案:(1)public成员 (2)protected成员 (3)不可访问 (4)接口不变 8.1.3 利用继承能够实现(1)。这种实现缩短了程序开发的时间,VC++中的(2)很 好地体现了这一点。 答案:(1)代码的复用 (2)MFC编程 8.1.4 一个派生类只有一个直接基类的情况称为(1),而有多个直接基类的情况称为 (2)。继承体现了类的(3)概念,这在MFC中得到了很好表现,MFC中只采用了(4)。 答案:(1)单继承 (2)多重继承 (3)层次 (4)单继承 8.1.5 C++中多态性包括两种多态性:(1)和(2)。前者是通过(3)实现的, 而后者是通过(4)和(5)来实现的。 答案:(1)编译时的 (2)运行时的 (3)函数和运算符的重载 (4)类继承关系 (5)虚函数 8.1.6 在基类中将一个成员函数说明成虚函数后,在其派生类中只要(1)、(2)和

(3)完全一样就认为是虚函数,而不必再加关键字(4)。如有任何不同,则认为是(5)而不是虚函数。除了非成员函数不能作为虚函数外,(6)、(7)和(8)也不能作为虚函数。 答案:(1)同虚函数名 (2)同参数表 (3)同返回类型。如基类中返回基类指针,而派生类中返回派生类指针是允许的 (4)virtual (5)重载 (6)静态成员函数 (7)内联函数 (8)构造函数 8.1.7 纯虚函数定义时在函数参数表后加(1),它表明程序员对函数(2),其本质 是将指向函数体的指针定为(3)。 答案:(1)=0 (2)不定义 (3)NULL 8.2简答题 8.2.1构造函数和析构函数可以继承吗?派生类构造函数各部分的执行次序是怎样的?答:构造函数和析构函数不可以继承。派生类构造函数各部分的执行次序是: 1.调用基类构造函数,按它们在派生类声明的先后顺序,依次调用。 2.调用新增成员对象的构造函数,按它们在类定义中声明的先后顺序,依次调用。 3.派生类的构造函数体中的操作。 8.2.2什么叫派生类的同名覆盖(override)? 答:如果派生类声明了一个和某个基类成员同名的新成员(当然如是成员函数,参数表也必须一样,否则是重载),派生类中的新成员就屏蔽了基类同名成员,类似函数中的局部变量屏蔽全局变量。称为同名覆盖(override)。 8.2.3派生类的析构函数中需完成什么任务?是否要编写对基数和成员对象的析构函数的 调用?为什么? 答:析构函数的功能是作善后工作,析构函数无返回类型也没有参数,情况比较简单。派生类析构函数定义格式与非派生类无任何差异,不要编写对基数和成员对象的析构函数的调用,只要在函数体内把派生类新增一般成员处理好就可以了,因为对新增的成员对象和基类的善后工作,系统会自己调用成员对象和基类的析构函数来完成。 8.2.4为什么要使用虚基类?怎样定义虚基类?用一个实例来解释虚基类在其派生类中的 存储方式。 答:在多重继承是有可能出现同一基类的两个拷贝,为避免这种情况,可使用虚基类。虚基类(virtual base class)定义方式如下: class派生类名:virtual 访问限定符基类类名{...}; class派生类名:访问限定符virtual基类类名{...}; virtual 关键字只对紧随其后的基类名起作用。

第五章 类与继承作业一

第五章类与继承作业一 一、填空选择题 1、(在同一包中)子类不能继承父类中的私有成员,除此之外,其它所有的成员都可以通过继承变为子类的成员。 2、给出如下的程序,A-E选项中与构造方法ConstOver重载的两个构造方法是:AC。 .public class ConstOver { publicConstOver (int x, int y, int z) { } } A.ConstOver ( ) { } B.ProtectedintConstOver ( ) { } C.PrivateConstOver (int z, int y, byte x) { } D.public Object ConstOver (int x, int y, int z) { } E.public void ConstOver (byte x, byte y, byte z) { } 3、已知类关系如下: class Employee; class Manager extends Employeer; class Director extends Employee; 则以下关于数据的语句正确的是:(A)。 A. Employee e=new Manager(); B. Director d=new Manager(); C. Director d=new Employee(); D. Manager m=new Director(); 4、(A)下面对类的申明哪个是正确的? A)public class Fred { publicint x = 0; public Fred (int x) { this.x = x; } } B)public class fred publicint x = 0; publicfred (int x) { this.x = x; } } C)public class Fred extends MyBaseClass, MyOtherBaseClass { publicint x = 0; public Fred (intxval) { x = xval; } } D)protected class Fred { privateint x = 0;

实验五 继承与多态

实验五继承与多态 专业班级学号姓名 实验学时 2 实验类型验证性实验地点数计学院实验中心实验时间指导老师 实验成绩 年月日一、实验目的: 理解继承与多态的概念,掌握三种访问控制的区别,掌握抽象类、接口与包的应用。 二、实验内容: 1. 参考教材P124,示例程序C5_17,掌握抽象类的应用。 2. 参考教材P128,示例程序C5_18,掌握接口的使用方法。 3. 参考教材P133,示例程序C5_20,掌握包的使用方法。 三、实验要求: 1.完成示例程序的验证。 2.写出实验报告。 四、实验步骤与结果:(由学生按照实验内容完成) 程序一 package ch01; import java.applet.Applet; import java.awt.Graphics; abstract class Shapes //定义一个抽象类Shapes { public int x,y; //x、y为画图的坐标 public int width,height; public Shapes(int x,int y,int width,int height) { this.x=x; this.y=y; this.width=width; this.height=height; } abstract double getArea( ); //求图形面积的抽象方法 abstract double getPerimeter( ); //求图形周长的抽象方法 } class Square extends Shapes //由抽象类Shapes派生的子类——矩形类 { @Override public double getArea( ){return(width*height);} @Override public double getPerimeter( ){return(2*width+2*height);} public Square(int x,int y,int width,int height) { super(x,y,width,height); } }

自考Java语言程序设计(一)第五章以后课后习题及答案

自考Java语言程序设计(一)第五张课后习题及答案 自考Java语言程序设计(一)第五章类的继承课后习题 五、类的继承 l.什么是继承?什么是父类?什么是子类?继承的特性可给面向对象编程带来什么好处?什么是单重继承?什么是多重继承? 2.观察下面的程序片断,指出其中的父类和子类,以及父类和子类的各个域和方法。 class SuperClass { int data; voidsetData(intnewData) { data=newData~ } intgetData() { return data~ } } class SubClass extends SuperClass { int suhData; void setSubData(intnewData) { suhData=new Data; } intgetData() { return subData; } } 3.“子类的域和方法的数目一定大于等于父类的域和方法的数目”,这种说法是否正确?为什么? 4. 在Java程序中,通过类的定义只能实现单重继承() 5.下列哪些说法是正确的? A、Java 语言只允许单一继承 B、Java 语言只允许实现一个接口 C、Java 语言不允许同时继承一个类并实现一个接口 D、Java 语言的单一继承使得代码更加可靠 6.Java中所有类都是类________的子类。

7.请写出下面程序的运行结果。 public class Test extends TT{ public void main(String args[]){ Test t = new Test("Tom"); } public Test(String s){ super(s); System.out.println("How do you do?"); } public Test(){ this("I am Tom"); } } www.Ehttps://www.doczj.com/doc/d14124205.html, class TT{ public TT(){ System.out.println("What a pleasure!"); } public TT(String s){ this(); System.out.println("I am "+s); } } 结果:________ 8.父类的成员在子类中的访问权限由决定。 9.对象的使用包括引用对象的成员变量和方法。通过运算符就能实现对对象成员变量的访问和对象 10.Java是面向对象语言,对象是客观事物的,对象与之是一一对应的,它是很具体的概念。 参考答案: l.答:继承是面向对象程序设计中两个类之间的一种关系。当一个类获取另一个类中所有非私有的数据和操作的定义作为它自己的部分或全部成分时,就称这两个类之间具有继承关系。被继承的类称为父类或超类,继承了父类或超类的所有数据和操作的类称为子类。 面向对象程序设计中的继承,可使得程序结构更加清晰,降低了编码和维护的工作量。如果一个类只能有一个父类,则这种继承关系称为单重继承;如果一个类可以有多个父类,则这种继承关系称为多重继承。 2.答: 父类SuperClass 父类的域data来源:考试大的美女编辑们 父类的方法setData(),getData() 子类SubClass 子类的域data,subData 子类的方法setSubData(),setData(),getData()采集者退散 3.答:这种说法是错误的,因为子类不一定能继承父类的所有域和方法,它只能

JAVA基础 第4章继承与多态_练习题_200910

第4章继承与多态一.选择题 1、编译与运行以下两文件结果就是( D )。 //文件P1、java package MyPackage; class P1{ void afancymethod(){ System、out、println("What a fancy method"); } } //文件P2、java package YourPackage; import MyPackage、*; public class P2 extends P1{ public static void main(String argv[]){ P2 p2 = new P2(); p2、afancymethod(); } } A.两个均通过编译,P2运行时输出What a fancy method B.没一个通过编译 C.两个均通过编译,但P2运行时出错 D.P1 通过编译,但P2出现编译错误 2.下列程序运行的结果就是( A )。 package a; package b; public class D{ public static void main(String args[]) { System、out、println("^_^,今天心情不错!"); } } A.出现编译错误 B.^_^,今天心情不错! C.通过编译,运行时出错 D.以上都不对 3.Java的核心类库中哪个包,Java系统能自动引入( B )。 A.java、io B.java、lang C.java、net D.java、util 4.下列程序运行结果就是( A )。 private class Base{ Base(){ int i = 100; System、out、println(i); }

继承与多态性习题参考答案

继承与多态性习题参考答案

————————————————————————————————作者:————————————————————————————————日期:

C++程序设计语言习题及实验指导 第8章继承与多态性习题参考答案 8.3 习题 8.3.1 选择题 题号 1 2 3 4 5 6 7 8 9 10 答案 C D A D A B C B D D 题号11 12 13 14 15 16 17 18 19 20 答案 D D A C B C C C A C 8.3.2 填空题 1.(1) a、b、c、x、y、z (2) b、y (3) c、z (4) a、x (5) b、c、x、y、z (6) b、y (7) y (8) b、c、z (9) a、x (10) b、c、x、y、z (11) y (12) y (13) z (14) a、b、c、x (15) b、c、x、y、z (16) y 2.私有 3.抽象 4.虚基 5.(1) 基类(2) 对象 6.(1) 静态(2) 编译(3) 虚函数 7.(1) 2 1 (2) 0 5 8.(1) 100 200 300 30 (2) 10 100 (3) 20 200 9.(1) 5 10 (2) end. (3) 20 10 10.(1) classA classB (2) end. (3) ~classB ~classA 11.(1) 10 (2) build B (3) build C (4) release A 12.(1) class B (2) class C (3) class D (4) 5 13.(1) 5 5 (2) 20 20 14.(1) 10 (2) 10 20 15.(1) 1 (2) 3 (3) 5 (4) 100 10 16.(1) B::f() (2) B::fun() (3) A::f() (4) B::fun() 17.(1) 姓名陈涛年薪6.8万元。(2) 姓名李原(3) 姓名李原月工资4000元18.(1) 110 (2) 2220 19.(1) protected 或public (2) Base1(s1),Base2(s2) 或Base2(s2),Base1(s1) (3) Base1::str (4) test.print() 20.(1) virtual void show()=0 (2) C(int,int,int) (注:参数可有任一名称) (3) b1(y) (4) &t 8.3.3 编程题 1.求长方形的面积和长方体的表面积、体积 #include class Rectangle{ protected: float L; // 长方形的长 float W; // 长方形的宽

java答案第五章

Java语言程序设计 第五章课后习题答案 1.什么是接口?接口起什么作用?接口与抽象类有何区别? 答:Java中的接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)。 作用:接口是面向对象的一个重要机制,使用接口可以实现多态继承;接口中的所有方法都是抽象的,这些抽象方法由实现这一接口的不同类型来具体;接口还可以用来实现不同类之间的常量共享。 与抽象类不同的是:接口允许在看起来不相干的类之间定义共同行为。 2.试编程证明接口中的属性都隐含为static及final,所有的方法都为public。 //定义接口Shape2D interface Shape2D{ double Pi=3.14; double area(); } //Circle类继承接口Shape2D public class Circle implements Shape2D{ double radius; public Circle(double r){radius=r;} public double area(){return Pi*radius*radius;} } //A类(测试接口中隐含final的area()方法) public class A extends Shape2D{ public double area(); } //test5_2 public class test5_2{ public static void main(String args[]){ Circle c=new Circle(10); System.out.println("Pi=3.14圆的面积:"+c.area()); SetPi b=new SetPi(3.00); System.out.println("改变Pi=3.00圆的面积:"+c.area()); } } 运行结果:

第五章 习题答案

答案: 一、单项选择题 1.C 2.D 3.A 4.D 5.C 6.B 7.A 8.B 9.A 10.D 二、简答题 1. 面向对象编程的三大特征:封装、继承和多态。封装:通过设置访问权限等方式封装了内部实现细节,使用者只需要知道外部接口。继承:子类可以继承父类的成员,又可以新增自己独有的成员,还可以覆盖父类的成员。多态:同名方法可以具有不同的行为,Java中有两种意义的多态:重载和重写。 2. 万物皆是对象,对象都有属性和行为。属性是对象所拥有的状态、数据,是静态的特征;行为是对象所拥有的功能、对数据的操作,是动态的特征,可能会影响到属性。 类封装了一类对象共有的属性和行为,是对具有相同属性和行为的对象的抽象。类是创建对象的模板,对象是类的具体实例。 3. (1)定义在类体内、方法外的变量称为成员变量。定义在方法体内部的变量,以及方法的形式参数,是方法所临时使用的变量,称为局部变量。 (2)成员变量在整个类体中都有效。而局部变量的有效范围仅限于定义它的方法体内,具体说明如下:①方法的形式参数:在整个方法体内有效;②方法体内独立定义的变量:在方法体中该变量定义之后的语句中有效;③选择、循环等语句块内定义的变量:只在语句块的{ }内有效。 (3)如果定义的成员变量没赋值,则系统为其提供缺省的初始值。所以成员变量定义后就有了确定的值,就可以使用。而方法的局部变量必须自行定义而且赋值后才能使用。(4)类成员变量在程序加载进内存时即开辟空间,实例成员变量在创建对象时开辟空间。局部变量只在方法调用时开辟空间,方法执行完毕后空间随即释放。 4. 多个方法名字相同,但参数个数或者类型不同,称为方法重载。方法返回值的类型和参数的名字不参与比较,方法重载是多态的一种体现。当调用方法时,根据传入的实参个数和类型,可以区分出调用的是哪一个方法。 5. 构造方法与所在类的类名完全相同,构造方法没有返回值类型,也不用void修饰。构造方法可以重载,一个类中可以定义多个构造方法。每个类中至少都有一个构造方法,如果未定义构造方法,系统会自动为该类生成一个缺省的没有参数的构造方法,如果类中定义了构造方法,就不再提供其他构造方法。 构造方法用new调用来创建对象,一般在构造方法中初始化成员变量。构造方法不能用static修饰。 三.编程题 1. classVecter3: def__init__(self,x=0,y=0,z=0): self.X=x self.Y=y

JAVA基础第章继承与多态练习题

第4章继承与多态一.选择题 1. 编译和运行以下两文件结果是( D )。 //文件P1.java package MyPackage; class P1{ void afancymethod(){ System.out.println("What a fancy method"); } } //文件P2.java package YourPackage; import MyPackage.*; public class P2 extends P1{ public static void main(String argv[]){ P2 p2 = new P2(); p2.afancymethod(); } } A.两个均通过编译,P2运行时输出What a fancy method B.没一个通过编译 C.两个均通过编译,但P2运行时出错 D.P1 通过编译,但P2出现编译错误 2.下列程序运行的结果是(A )。 package a; package b; public class D{ public static void main(String args[]) { System.out.println("^_^,今天心情不错!"); } } A.出现编译错误 B.^_^,今天心情不错! C.通过编译,运行时出错 D.以上都不对 3.Java的核心类库中哪个包,Java系统能自动引入(B )。 A.java.io B.https://www.doczj.com/doc/d14124205.html,ng C.https://www.doczj.com/doc/d14124205.html, D.java.util 4.下列程序运行结果是( A )。 private class Base{ Base(){ int i = 100; System.out.println(i); }

第5章继承与多态

第5章继承与多态 本章讨论面向对象程序设计另外两个最重要的特点:继承和多态。 继承是面向对象程序设计方法中实现软件重用的一种重要手段,通过继承可以更有效地组织程序结构,明确类之间的关系,并充分利用已有的类来创建新类,通过继承可以实现代码的重用,以完成更复杂的设计、开发。 多态则可以统一多个相关类的对外接口,并在运行时根据不同的情况执行不同的操作,提高类的抽象度和灵活性。 5.1 子类、父类与继承机制 5.1.1 继承的概念 在类的定义过程中,继承是一种由已有的类创建新类的机制。继承而得到的类为子类,被继承的类为父类,父类包括所有直接或间接被继承的类。 在类的声明中加入extends子句就可以创建一个类的子类: class SubClass extends SuperClass {……} Java中不通过extends关键字支持多重继承,即extends之后只能有唯一的父类。如果缺省extends子句,则该类为https://www.doczj.com/doc/d14124205.html,ng.Object的子类。子类可以继承父类中访问权限设定为public、protected和包可访问的成员变量和方法,但是不能继承访问权限为private的成员变量和方法。 一个父类可以同时拥有多个子类,而每一个子类则只能有唯一的父类。子类是对公共域和方法在功能、内涵方面的扩展和延伸。 父类、子类间的关系具有: 共享性即子类可以共享父类的公共域和方法。 差异性即子类和父类一定会存在某些差异,否则就应该是同一个类。 层次性即由Java规定的单继承性,每个类都处于继承关系中的某一个层面。 5.1.2 类的层次 Java语言中类的是有严格的层次结构的。 除Object类之外,每个类都继承惟一的父类。这种继承性性质使得类的层次结构形成了如图所示的一种树状结构。 Object类定义和实现了Java系统所需要的众多类的共同行为,它是所有类的父类,也即这个树状结构中的根类,所有的类都是由这个类继承、扩充而来的,这个Object类定义在https://www.doczj.com/doc/d14124205.html,ng包中。 5.2 继承的实现 5.2.1 子类的定义 定义一个子类,即在定义一个类的时候加上extends关键字,并在之后带上其父类名,其一般格式为:[类的修饰符] class <子类名> extends <父类名>{ <域定义>; <方法定义>; } 这和前面定义类的格式并没有什么区别,只是在定义子类时“extends <父类名>”不再是可选项。

05继承与多态

1.下面关于继承的描述正确的有:【选择两项】AD A在java 中只允许单一继承。// B在java 中一个类只能实现一个接口。//一个类只能实现多个接口 C在java 中一个类不能同时继承一个类和实现一个接口。//所有的类都继承object D java 的单一继承使代码更可靠。// 2.下面程序中第10行调用的方法是在第几行声明的:【选择一项】D 1 class Person { 2 public void printValue(int i, int j) {/*…*/ } 3 public void printValue(int i){/*...*/ } 4 } 5 public class Teacher extends Person { 6 public void printValue() {/*...*/ } 7 public void printValue(int i) {/*...*/} 8 public static void main(String args[]){ 9 Person t = new Teacher();//多态 10 t.printValue(10); //多态调用子类方法、父类属性 11 } 12 } A第2行 B第3行 C第6行 D第7行 3.对于下面给定的代码,下面哪些选项可以添加到程序的第11行处:【选择一项】D 1 class Person { 2 String name,department; 3 public void printValue(){ 4 System.out.println("name is "+name); 5 System.out.println("department is "+department); 6 } 7 } 8 public class Teacher extends Person { 9 int salary; 10 public void printValue(){ 11 //doing the same as in the parent method printValue() 12 System.out.println("salary is "+salary); 13 } 14 } A printValue();//递归 B this.printValue();//递归 C Person.printValue();//不是静态的

相关主题
文本预览
相关文档 最新文档