核心技术
第十章 接口、继承和多态
10.1 类的继承
package com;
public class Test {
public Test(){
//构造方法
}
protected void doSomething(){
//成员方法
}
protected Test doIt(){
//方法返回值类型为Test类型
return new Test();
}
}
package com;
class Test2 extends Test{
public Test2(){
super();
super.doSomething();
}
public void doSomethingnew(){
//新增方法
}
public void doSomething(){
//重写父类方法,存储权限改变。
}
protected Test2 doIt(){
return new Test2();//重写父类方法,方法返回值类型为Test2类型。
}
}
重写:在子类中将父类的成员方法的名称保留,重写成员方法的实现内容,更改成员方法的存储权限,或是修改成员方法的返回值类型。
重写父类方法时修改方法的修饰权限只能从小的范围到大的范围改变。
重写父类方法修改返回值类型时,重写的返回值类型必须是父类中同一方法返回值类型的子类。
重构:特殊的重写方式,子类与父类的成员方法返回值、方法名称、参数类型及个数完全相同,唯一不同的是方法实现内容。
package com;
class Parent {
Parent() {
System.out.println("调用父类的panrent()的构造方法");
}
}
class SubParent extends Parent{
SubParent(){
System.out.println("调用子类的SubParent()构造方法");
}
}
class Subroutine extends SubParent{
Subroutine(){
System.out.println("调用子类的Subroutine()构造方法");
}
public static void main(String[] args){
Subroutine s=new Subroutine();
}
}
实例化子类对象首先实例化顶级父类,然后是上一级父类,最后是子类
10.2 Object类
Object类是所有类的父类。,是java类中最高层类。
class Anything{} 等价于 class Anything extends Object
-
getClass()方法
返回对象执行时的Class实例,然后使用此实例调用getName()方法可取的类的名称 getClass().getname(); 可与toString()方法联用
-
toString()方法
package com; public class ObjectInstance { public String toString(){ return"在"+getClass().getName()+"类中重写toString()方法"; } public static void main(String[] args){ System.out.println(new ObjectInstance()); } }
-
equals()方法
package com; class V{ } public class OverWriteEquals { public static void main(String[] args){ String s1="123"; String s2="123"; System.out.println(s1.equals(s2)); V v1=new V(); V v2=new V(); System.out.println(v1.equals(v2)); } } 结果: true false equals()方法的默认实现是使用==运算符比较两个对象的引用地址,而不是比较两个对象的内容。
10.3 对象类型的转换
10.3.1 向上转型
- 从一个较具体的类到较抽象的类之间的转换
- 总是安全的
10.3.2 向下转型
-
较抽象类转换为较具体的类。
-
必须使用显式类型转换:
-
Quadrangle q=new Parallelogram(); Parallelogram p=(Parallelogram)q;
10.4 instanceof判断对象类型
-
判断是否一个类实现了某个接口
-
判断一个实例对象是否属于一个类
-
myobject instanceof ExampleClass; 返回值为布尔值
package com; class Quadrangle{ public static void draw(Quadrangle q){ } } class Square extends Quadrangle{ } class Anything{ } public class Parallelogram extends Quadrangle{ public static void main(String[] args){ Quadrangle q1=new Quadrangle(); if(q1 instanceof Parallelogram){ Quadrangle p1=q1; System.out.println("向下转型"); } Parallelogram q2=new Parallelogram(); if(q2 instanceof Parallelogram){ Quadrangle p2=q2; System.out.println("向上转型"); } if(q1 instanceof Square){ Square s=(Square)q1; System.out.println("向上转型"); } //由于q对象不为Anything类的对象,所以这条语句错误 //System.out.println(q instanceof Anything); } }
10.5 方法的重载
在同一个类中允许同时存在一个以上的同名方法,只要这些方法的参数个数或类型不同即可
package com;
public class OverLoadTest {
public static int add(int a,int b){
return a+b;
}
public static double add(double a,double b){
return a+b;
}
public static int add(int a){
return a;
}
public static int add(int a,double b){
return 1;
}
public static int add(double a,int b){
return 1;
}
public static void main(String[] args){
System.out.println("调用add(int,int)方法"+add(1,2));
System.out.println("调用add(double,double)方法"+add(2.1,3.3));
System.out.println("调用add(int)方法"+add(1));
}
}
重载条件:参数类型不同/参数顺序不同/参数个数不同
不定长参数方法
public static int add(int...a){
int s=0;
for(int i=0;i<a.length;i++){
s+=a[i];
}
return s;
}
System.out.println("调用不定长参数方法"+add(1,2,3,4,5,6,7,8,9));
System.out.println("调用不定长参数方法"+add(1));
10.6 多态
package com;
public class CopyOfQuadrangle {
private CopyOfQuadrangle[] qtest=new CopyOfQuadrangle[6];//实例化保存四边形对象的数组对象
private int nextIndex=0;
public void draw(CopyOfQuadrangle q){
if(nextIndex < qtest.length){
qtest[nextIndex]=q;
System.out.println(nextIndex);
nextIndex ++;
}
}
public static void main(String[] args){
CopyOfQuadrangle q=new CopyOfQuadrangle();
q.draw(new CopyOfSquare() );
q.draw(new CopyOfParallelogramgle() );
}
}
class CopyOfSquare extends CopyOfQuadrangle {
public CopyOfSquare (){
System .out .println("正方形") ;
}
}
class CopyOfParallelogramgle extends CopyOfQuadrangle {
public CopyOfParallelogramgle (){
System .out .println("平行四边形") ;
}
}
程序无需在所有的子类中定义执行相同功能的方法,避免了大量重复代码的开发,同时,只要实例化一个继承父类的子类对象即可调用相应的方法。这里只要维护父类中的这个方法即可。
10.7 抽象类与接口
- 图形类,不能使用具体的语言进行描述。称抽象类
10.7.1 抽象类
public abstract class Test{
abstract void testAbstract();//定义抽象方法
}
- 只要类中有一个抽象方法,此类就被标记为抽象类
- 抽象类被继承后需要实现其中所有的抽象方法,保证相同的方法名称、参数列表和相同返回值类型创建出非抽象方法,当然也可以是抽象方法。
10.7.2 接口
-
接口是抽象类的延伸,接口中的所有方法都没有方法体,是纯粹的抽象类
-
接口定义: public interface drawTest{ void draw();//接口内的方法,省略abstract关键字 }
-
一个类实现一个接口: public class Parallelogram extends Quadrangle implements drawTest{ }
-
在接口中定义的任何字段都自动是static和final的
-
在接口中定义的方法必须被定义为public或abstract形式
-
package com; interface drawTest{ //定义接口 public void draw(); //定义方法 } class ParalleolgramgleUseInterface extends QuadrangleUseInterface implements drawTest{ public void draw(){//由于该类实现了接口,所以需要覆盖draw()方法 System .out .println("平行四边形.draw()") ; } //void doAnyThing(){ //} } class SquareUseInterface extends QuadrangleUseInterface implements drawTest{ public void draw(){ System .out .println("正方形.draw()") ; } //void doAnyThing(){ //} } class AntThingUseInterface extends QuadrangleUseInterface{ void doAnyThing(){ } } public class QuadrangleUseInterface { public void doAnyTthing(){ } public static void main(String[] args){ drawTest []d={//将平行四边形类对象和正方形类对象向上转型为drawTest接口形式 new SquareUseInterface(), new ParalleolgramgleUseInterface() }; for (int i=0;i<d.length;i++){ d[i].draw(); } //不将正方形对象向上转型为接口类型,直接调用draw()方法,也可实现功能 /* SquareUseInterface s=new SquareUseInterface(); s.draw();*/ } }
-
无论将一个类向上转型为父类对象,还是抽象父类对象,还是该类实现接口,都可以。
-
但是为什么要转为接口类型呢?不转化也可以实现功能啊。
-
接口与继承
-
class 类名 implements 接口1,接口2,……,接口n interface intf1{} interface intf2 extends intf1{}
-
-
使用接口可实现多重继承