Java继承,抽象类与接口的应用
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Java继承, Java继承,抽象类与接口的应用 继承
1.继承及继承实例 2.方法重写(Overwrite) 3.super关键字 4.方法重载(Overload) 5.final修饰符 6.abstract修饰符 7.抽象类 8.接口 9.接口和抽象类对比 10.接口和抽象类使用场合实例 11.总结
继承中的构造方法
在父类Door中定义无参构造方法: public Door(){ System.out.println("这是父类构造方法!"); } 在子类CommonDoor中定义无参构造方法: public CommDoor(){ System.out.println("这是子类构造方法"); } 测试: CommDoor cd=new CommDoor(); 结果: 这里可以得出一个结论: 实例子类时,子类默认会自动调用父 类的无参构造方法。
在此基础上,我们可以回顾几个访问修饰符。
final修饰符
final修饰符可以修饰类,变量,方法。
被final修饰的变量叫做常量,址不能被修改,如final int PI=3.14; 被final修饰的类不能被继承。 被final修饰的方法不能被重写。
abstract修饰符
abstract修饰符可以修饰类,方法。 被abstract修饰的类叫做抽象类,抽象类不能被实例化。 被abstract修饰的方法叫做抽象方法,抽象方法没有方法体,不提供具体实现。 public abstract class Door { public abstract void open(); } 所谓不能实例,就是指不能:Door door=new Door(); 所谓无方法体,不实现就是指:open方法没有具体的指定实现。那么定义这样的 类和方法有什么用呢? 我们最终当然要为这样的类和方法提供一个实现,这个实现就是继承他的类,他的子类可以 为抽象方法提供具体的实现。 抽象类通常代表一个抽象概念,可以用一句话来概括抽象类的用途:抽象类是用来继承的。 反过来可以说具体类不是用来继承的,只要有可能,我们不要从具体类继承——之前我们的 做法虽然实现了功能,但是没有达到思想上的真正意义。
创建子类——CommonDoor和SecurityDoor CommonDoor和 创建子类 CommonDoor
文件结构: 这三个类都放在同一个demo1包下:
普通门CommDoor : public class CommDoor extends Door { } 安全门: public class SecurityDoor extends Door { }
重载测试
测试: sd.open(123456); //使用密码开门 sd.open("万能钥匙"); //使用钥匙开门 sd.open(1802,"学员"); //根据房号和访客姓名开门 结果:
可以看到,对于不同的请求方式,程序能作出不同的响应结果。
重载和重写小结
重载: 发生在一个类中,方法名相同,参数列表不同(包括类型,个数,顺序)。 重写(覆盖): 发在在有继承情况的类中,子类方法和父类声明完全一致。
son:代表子类,又叫做超类。 Base:代表父类,又叫做基类。
继承的基本语法
语法: public class 子类名 extends 父类名{
}
注意:子类只能继承父类public和protected修饰的属 性和方法。
下面,我们通过一个实际的例子来学习继承。
创建父类Door 创建父类Door
所有门都拥有开(open)和关(close)这样的动作,不管是普通的门还是安全门, 所以我们这里定义一个公用的父类Door类,并且默认的认为所有的门的名字都叫门。 父类: public class Door { public String doorName="门"; //门的名字 public void open(){ //开门方法 System.out.println("门开了!"); } public void close(){ //关门方法 System.out.println("门关了"); } }
super关键字 super关键字
如果在子类中重写了父类属性,如在Security中重新定义了doorName属性: private String doorName="安全门"; 要想再访问到父类的属性,则可以使用: super.doorName;
测试: System.out.println(this.doorName+" "+ super.doorName); 结果:
这种在子类中重新定义父类已有方法的行为就是重写,重写是多态的一 种体现形式。
重写测试
这里重写了父类里的open方法,相当于将父类的open方法覆盖掉了。 当执行: SecurityDoor sd=new SecurityDoor(); sd.open(); 步骤如下: 1、在SecurityDoor类查找open方法,如果有责直接调用,否则执行下一步 2、在父类中查找open方法,如果有则调用 输出结果:
abstract修饰符
使用abstract有以下几个需要遵循的原则: 抽象类中可以没有抽象方法,但包含抽象方法的类就必须是抽象类。 抽象方法不能是静态的。 抽象类及抽象方法不能被final修饰。
抽象类不象具体类那样描述一类具体事物,它是提取多种具有相似性的具体事物的 共同特征而产生的 。而不是一个具体描述对象的类。 同时抽象类和抽象方法其实是面向契约的一种体现,抽象类就相当于一个制定者。 对于某些强制要被定义和实现的方法,可以定义为抽象方法,那么一旦有子类继承 该抽象类,子类就必须要按照契约来实现这个抽象方法。
方法重载(Overload) 方法重载(Overload)
假设,我们的安全门现在有多种开门方式,可以使用钥匙开门,使用6位密码开门, 输入房号和访客姓名请求开门三种方式。 那么我们可以做如下定义: 重载的特点: public void open(String key){ System.out.println("/*--用钥匙开安全门,模拟验证钥匙是否正确--*/"); 方法名都相同,参 System.out.println("门开了!"); 数列表不同。 } public void open(int pwd){ System.out.println("/*--用6位密码开门,模拟验证密码是否正确--*/"); System.out.println("门开了!"); } public void open(int doorNo,String visitName){ System.out.println("/*--"+visitName+"请求"+doorNo+"开门,模拟确定是否开门--*/"); System.out.println("门开了!"); } 不允许仅仅返回值不同的重载。如: public void open(String key){……}和public String open(String key){……} 是不能通过编译的。
方法重载(Overload) 方法重载(Overload)
方法重载(Overload),是类的同一功能(方法)有多种实现方式。 其实重载在我们学习Math数学类的时候已经有所接触了,如下:
这里有四个都叫max的方法,但是他们的参数列表不同,这样就可以实现, 当我们不论输入任何两个数字型(double,int,float,long)的参数的时 候,都能返回最大值。 不需要定义doubleMax,floatMax,intMax,longMax这样的方法。
用抽象类来实现之前开关门的业务
现在我们使用抽象类来实现之前的功能。 public abstract class Door { public void open(){ System.out.println("门开了!"); } public void close(){ System.out.println("门关了"); } } 这样看似在结果上没有任何变化,但是却已经符合抽象思维某种角度和语 义——就相当于,水果是抽象类,那么苹果,梨就是具体类,由具体类负 责来实例对象,抽象类只负责描述抽象特征和行为。 注意:如果一个类继承了抽象类,但没有实现它所有的抽象方法,那么这 个类也是抽象类。
什么是继承
在第一节课的时候,我们就已经初始了继承的概念: 子类自动共享父类数据结构和方法的机制,这是类之间的一种关系。 继承也是提高代码复用的有力手段,当多个类之间存在相同的属性和方法时,就可以考虑 继承,从这些类中抽象出父类——在父类中定义这些相同的属性和方法,子类无需再定 义这些相同的属性和方法,只需要通过extends语句来声明继承关系即可: public class Son extends Base{ …… } 继承具有单根性:即一个类只能继承最多一个类。 不能出现: public class Son extends Base,Base2{……} 但是Base类可以继承其他类。
重写必须保证子类的方法定义完全和父类相同,不允许返回值类型不同的重写。 如: public String open(){……}
super关键字 super关键字
一般在以下情况我们会用到super关键字: 1.在子类构造方法中,通过super调用父类构造方法 2.在子类中访问父类被覆盖重写的方法和属性 现在给Door添加构造方法,如下: public Door(String doorName){ this.doorName=doorName; } 在SecurityDoor中可以如下定义: public SecurityDoor(String doorName,String brand){ super(doorName); this.brand=brand; } 说明,SecurityDoor有一个自己的brand属性。 这里的super代表调用父类的构造 方法。
可以发现,在CommDoor和SecurityDoor中我们一行代码都没有写,只是继承了 Door类,就可以直接使用open和close方法了。 这正是继承的特点——子类可以共享父类的数据和方法。 如果说类的数量很多,那么这种优势就更加显而易见了。 但是继承的弱点是:打破了封装,当父类一旦改变,子类也就可能发生变化,类的耦 合度过高,不符合我们高内聚低耦合的设计原则。
方法重写(Overwrite) 方法重写(Overwrite)
方法重写(Overwrite)又叫方法覆盖(Override),是有继承关系的类之间的一种多 态特性。 如果,对于一般门,当调用open方的时候直接输出“门开了”就好了,可是对于安 全门我们可能在开门之前需要做一个身份验证,以确定是否真的要开门。 那么我们就需要在子类里面重写父类的open方法。 public void open(){ System.out.println("/*--安全门,模拟执行了安全验证--*/"); System.out.println("门开了!"); }
继承测试
public static void main(String[] args) { CommDoor cd=new CommDoor(); System.out.println(cd.doorName); cd.open(); cd.close(); SecurityDoor sd=new SecurityDoor(); System.out.println(sd.doorName); sd.open(); sd.close(); } 结果:
用抽象类来实现之前开关门的业务
如果我们现在要求每个门都必须有一个提供自己门牌号的方法——由于每个门的门牌号百度文库都不一样,所以可以定义一个抽象方法,由子类具体实现内容。
在Door抽象类中定义抽象方法: 相当于契约。 public abstract void theNo();
在子类中实现抽象方法: public void theNo() { System.out.println("我是安全门No2085"); }
1.继承及继承实例 2.方法重写(Overwrite) 3.super关键字 4.方法重载(Overload) 5.final修饰符 6.abstract修饰符 7.抽象类 8.接口 9.接口和抽象类对比 10.接口和抽象类使用场合实例 11.总结
继承中的构造方法
在父类Door中定义无参构造方法: public Door(){ System.out.println("这是父类构造方法!"); } 在子类CommonDoor中定义无参构造方法: public CommDoor(){ System.out.println("这是子类构造方法"); } 测试: CommDoor cd=new CommDoor(); 结果: 这里可以得出一个结论: 实例子类时,子类默认会自动调用父 类的无参构造方法。
在此基础上,我们可以回顾几个访问修饰符。
final修饰符
final修饰符可以修饰类,变量,方法。
被final修饰的变量叫做常量,址不能被修改,如final int PI=3.14; 被final修饰的类不能被继承。 被final修饰的方法不能被重写。
abstract修饰符
abstract修饰符可以修饰类,方法。 被abstract修饰的类叫做抽象类,抽象类不能被实例化。 被abstract修饰的方法叫做抽象方法,抽象方法没有方法体,不提供具体实现。 public abstract class Door { public abstract void open(); } 所谓不能实例,就是指不能:Door door=new Door(); 所谓无方法体,不实现就是指:open方法没有具体的指定实现。那么定义这样的 类和方法有什么用呢? 我们最终当然要为这样的类和方法提供一个实现,这个实现就是继承他的类,他的子类可以 为抽象方法提供具体的实现。 抽象类通常代表一个抽象概念,可以用一句话来概括抽象类的用途:抽象类是用来继承的。 反过来可以说具体类不是用来继承的,只要有可能,我们不要从具体类继承——之前我们的 做法虽然实现了功能,但是没有达到思想上的真正意义。
创建子类——CommonDoor和SecurityDoor CommonDoor和 创建子类 CommonDoor
文件结构: 这三个类都放在同一个demo1包下:
普通门CommDoor : public class CommDoor extends Door { } 安全门: public class SecurityDoor extends Door { }
重载测试
测试: sd.open(123456); //使用密码开门 sd.open("万能钥匙"); //使用钥匙开门 sd.open(1802,"学员"); //根据房号和访客姓名开门 结果:
可以看到,对于不同的请求方式,程序能作出不同的响应结果。
重载和重写小结
重载: 发生在一个类中,方法名相同,参数列表不同(包括类型,个数,顺序)。 重写(覆盖): 发在在有继承情况的类中,子类方法和父类声明完全一致。
son:代表子类,又叫做超类。 Base:代表父类,又叫做基类。
继承的基本语法
语法: public class 子类名 extends 父类名{
}
注意:子类只能继承父类public和protected修饰的属 性和方法。
下面,我们通过一个实际的例子来学习继承。
创建父类Door 创建父类Door
所有门都拥有开(open)和关(close)这样的动作,不管是普通的门还是安全门, 所以我们这里定义一个公用的父类Door类,并且默认的认为所有的门的名字都叫门。 父类: public class Door { public String doorName="门"; //门的名字 public void open(){ //开门方法 System.out.println("门开了!"); } public void close(){ //关门方法 System.out.println("门关了"); } }
super关键字 super关键字
如果在子类中重写了父类属性,如在Security中重新定义了doorName属性: private String doorName="安全门"; 要想再访问到父类的属性,则可以使用: super.doorName;
测试: System.out.println(this.doorName+" "+ super.doorName); 结果:
这种在子类中重新定义父类已有方法的行为就是重写,重写是多态的一 种体现形式。
重写测试
这里重写了父类里的open方法,相当于将父类的open方法覆盖掉了。 当执行: SecurityDoor sd=new SecurityDoor(); sd.open(); 步骤如下: 1、在SecurityDoor类查找open方法,如果有责直接调用,否则执行下一步 2、在父类中查找open方法,如果有则调用 输出结果:
abstract修饰符
使用abstract有以下几个需要遵循的原则: 抽象类中可以没有抽象方法,但包含抽象方法的类就必须是抽象类。 抽象方法不能是静态的。 抽象类及抽象方法不能被final修饰。
抽象类不象具体类那样描述一类具体事物,它是提取多种具有相似性的具体事物的 共同特征而产生的 。而不是一个具体描述对象的类。 同时抽象类和抽象方法其实是面向契约的一种体现,抽象类就相当于一个制定者。 对于某些强制要被定义和实现的方法,可以定义为抽象方法,那么一旦有子类继承 该抽象类,子类就必须要按照契约来实现这个抽象方法。
方法重载(Overload) 方法重载(Overload)
假设,我们的安全门现在有多种开门方式,可以使用钥匙开门,使用6位密码开门, 输入房号和访客姓名请求开门三种方式。 那么我们可以做如下定义: 重载的特点: public void open(String key){ System.out.println("/*--用钥匙开安全门,模拟验证钥匙是否正确--*/"); 方法名都相同,参 System.out.println("门开了!"); 数列表不同。 } public void open(int pwd){ System.out.println("/*--用6位密码开门,模拟验证密码是否正确--*/"); System.out.println("门开了!"); } public void open(int doorNo,String visitName){ System.out.println("/*--"+visitName+"请求"+doorNo+"开门,模拟确定是否开门--*/"); System.out.println("门开了!"); } 不允许仅仅返回值不同的重载。如: public void open(String key){……}和public String open(String key){……} 是不能通过编译的。
方法重载(Overload) 方法重载(Overload)
方法重载(Overload),是类的同一功能(方法)有多种实现方式。 其实重载在我们学习Math数学类的时候已经有所接触了,如下:
这里有四个都叫max的方法,但是他们的参数列表不同,这样就可以实现, 当我们不论输入任何两个数字型(double,int,float,long)的参数的时 候,都能返回最大值。 不需要定义doubleMax,floatMax,intMax,longMax这样的方法。
用抽象类来实现之前开关门的业务
现在我们使用抽象类来实现之前的功能。 public abstract class Door { public void open(){ System.out.println("门开了!"); } public void close(){ System.out.println("门关了"); } } 这样看似在结果上没有任何变化,但是却已经符合抽象思维某种角度和语 义——就相当于,水果是抽象类,那么苹果,梨就是具体类,由具体类负 责来实例对象,抽象类只负责描述抽象特征和行为。 注意:如果一个类继承了抽象类,但没有实现它所有的抽象方法,那么这 个类也是抽象类。
什么是继承
在第一节课的时候,我们就已经初始了继承的概念: 子类自动共享父类数据结构和方法的机制,这是类之间的一种关系。 继承也是提高代码复用的有力手段,当多个类之间存在相同的属性和方法时,就可以考虑 继承,从这些类中抽象出父类——在父类中定义这些相同的属性和方法,子类无需再定 义这些相同的属性和方法,只需要通过extends语句来声明继承关系即可: public class Son extends Base{ …… } 继承具有单根性:即一个类只能继承最多一个类。 不能出现: public class Son extends Base,Base2{……} 但是Base类可以继承其他类。
重写必须保证子类的方法定义完全和父类相同,不允许返回值类型不同的重写。 如: public String open(){……}
super关键字 super关键字
一般在以下情况我们会用到super关键字: 1.在子类构造方法中,通过super调用父类构造方法 2.在子类中访问父类被覆盖重写的方法和属性 现在给Door添加构造方法,如下: public Door(String doorName){ this.doorName=doorName; } 在SecurityDoor中可以如下定义: public SecurityDoor(String doorName,String brand){ super(doorName); this.brand=brand; } 说明,SecurityDoor有一个自己的brand属性。 这里的super代表调用父类的构造 方法。
可以发现,在CommDoor和SecurityDoor中我们一行代码都没有写,只是继承了 Door类,就可以直接使用open和close方法了。 这正是继承的特点——子类可以共享父类的数据和方法。 如果说类的数量很多,那么这种优势就更加显而易见了。 但是继承的弱点是:打破了封装,当父类一旦改变,子类也就可能发生变化,类的耦 合度过高,不符合我们高内聚低耦合的设计原则。
方法重写(Overwrite) 方法重写(Overwrite)
方法重写(Overwrite)又叫方法覆盖(Override),是有继承关系的类之间的一种多 态特性。 如果,对于一般门,当调用open方的时候直接输出“门开了”就好了,可是对于安 全门我们可能在开门之前需要做一个身份验证,以确定是否真的要开门。 那么我们就需要在子类里面重写父类的open方法。 public void open(){ System.out.println("/*--安全门,模拟执行了安全验证--*/"); System.out.println("门开了!"); }
继承测试
public static void main(String[] args) { CommDoor cd=new CommDoor(); System.out.println(cd.doorName); cd.open(); cd.close(); SecurityDoor sd=new SecurityDoor(); System.out.println(sd.doorName); sd.open(); sd.close(); } 结果:
用抽象类来实现之前开关门的业务
如果我们现在要求每个门都必须有一个提供自己门牌号的方法——由于每个门的门牌号百度文库都不一样,所以可以定义一个抽象方法,由子类具体实现内容。
在Door抽象类中定义抽象方法: 相当于契约。 public abstract void theNo();
在子类中实现抽象方法: public void theNo() { System.out.println("我是安全门No2085"); }