面向对象三大特征之二(继承多态),抽象类接口
摘要:
我们上一章学到了封装的概述基本入门,今天我们学习的内容比较多,把面向对象三大特征说完,还有多态,和接口,内容比较多,里面还有一部分面试问题,废话不多说,大家准备接收吧.
提供一张结构图
1 封装补充知识
1.1 this关键字
this:代表当前类对象的地址值引用 Student s = new Student() ;
s---->空间地址值的引用;
this的出现:
为了防止局部变量隐藏了成员变量,
构造方法
public Phne(String brand ,int price){
this.brand = brand ;
thi.price = price ;
}
setxxx()
public void setBrand(String brand){
this.brand = brand ;
}
this的用法:
this.变量名; 变量名:访问本类的成员变量名
this.方法名() ; 访问的本类的成员方法
this()----- 访问本类无参构造方法...
this(xxx) 访问本类的有参构造方法...
等我们学了super之后会对俩个关键字做对比和区别的
1.2 什么是匿名对象:
---->就是没有名字的对象(移动端完成APP开发中使用多一些)
Java中有一个概念:
匿名对象: 毋庸置疑,没有名字对象;
类名 对象名 = new 类名();
匿名对象的格式: new 类名();
直接在堆内存开辟空间,使用完毕就要被回收,可以节省内存;
- 匿名对象可以作为参数传递
- 创建完毕之后,没有栈内存指向,所以使用完毕,立即被GC(垃圾回收器回收)
- 一般情况:匿名对象使用一次即可,这样不需要过多的去开辟堆内存空间,直接被回收;
1.3 匿名对象的好处
1)匿名对象可以作为参数传递 :可以把上面那个代码改进
2)匿名对象可以节省内存空间,因为压根没有栈内存空间,不需要开辟,直接开辟堆内存空间
3)匿名对象一般适用于一次即可,使用完毕,直接被jvm的GC(垃圾回收器)的回收;
1.4 方法形式参数如果是一个类(引用类型),当调用该方法的时候,实际参数如何传递(重点)
如果方法的形式参数是类,实际参数传递,需要传递是当前类的具体类对象(以后经常会用到,可能是出题者提供的类或者jdk提供的类)
class StudentTest{
public static void main(String[] args){
//补全代码: 需求:访问StudentDemo类的method方法
//创建StudentDemo类对象
//有名字对象
StudentDemo sd = new StudentDemo() ;
//new 一个具体的学生
Student s = new Student() ;
sd.method(s) ;//实际参数
}
}
class Student{
public void study(){
System.out.println("Good good stduy ,Day day up!!!") ;
}
}
class StudentDemo{
public void method(Stduent s){ //形式参数:引用类型:Student类型
s.study() ;
}
}
1.5 构造方法的特点以及注意事项
构造方法特点:
1)方法名和类名相同,
2)没有具体返回值类型,
3)连void都没有 public 方法名和类名相同(){ }
构造方法的目的:
就是为给类的成员初始化 Phone p = new Phone();//无参构造方法
1)栈内存开辟空间
2)堆内存申请空间
3)进行系统默认初始化,为成员变量 4)setXXX(“xxx”) /有参构造方法:显示初始化…
构造方法的注意事项
1)当在书写一个标准类的时候,没有给出任何构造方法.系统会默认提供无参构造方法
2)如果提供了一个类的有参构造方法,系统就不会构造方法,所以,建议永远给出无参构造方法;
3)构造方法是可以重载的;
创建对象就是创建实例
1.6 一个类成员的组成以及一个类的标准写法
一个类的组成
1)成员变量
2)构造方法
3)成员方法
一个类的标准类的写法:
1)成员变量私有化
2)无参永远给出的,有参构造根据题意要求(没有明确,全部提供)
3)成员方法,根据题意要求(没有明确是否带参,是否有返回值,直接输 出语句)
标准类的代码体现
/**
*
* 学生事物:
* 属性:姓名,年龄,性别,网名
*
* 行为:学习JavaSE,会玩lol
*
*
* 一个标准类的写法:
* 成员变量私有化
* 提供对外的公共访问方法,setXXX()/getXXX()
* 提供无参构造/ 有参构造方法 (根据需求进行判断)
*
* 在StudentTest中进行测试学生信息以及成员方法;
*
*
* 给成员变量赋值:
* 1)setXXX方法赋值
* 2)有参构造方法赋值
*/
//测试类
public class StudentTest {
public static void main(String[] args) {
//方式1:无参构造方法 +setXXX()/getXXX()
//类名 对象名 = new 类名();
Student s = new Student() ;
s.setName("高圆圆") ;
s.setAge(20) ;
s.setSex("女") ;
s.setUsername("杨桃") ;
System.out.println("学生姓名是:"+s.getName()+",年龄是:"+
s.getAge()+",性别是:"+s.getSex()+",网名是:"+s.getUsername()) ;
//其他成员方法
s.studyJavaSE();
s.playLol();
System.out.println("---------------------------------------");
//方式2:有参构造方法 +getXXX()就可以了
Student s2 = new Student("赵又廷",25,"男","小赵") ;
System.out.println("学生姓名是:"+s2.getName()+",年龄是:"+
s2.getAge()+",性别是:"+s2.getSex()+",网名是:"+s2.getUsername()) ;
s2.studyJavaSE();
s2.playLol();
}
}
package com.qf.test_06;
//学生类
public class Student {
//属性:姓名,年龄,性别,网名 ---私有化
private String name ; //姓名
private int age ; //年龄
private String sex ; //性别
private String username ; //网名
//永远给出无参构造方法
//alt+fn+ins--->Constructor---->select none--->生成无参构造方法
public Student() {
}
//有参构造方法
//alt+fn+ins---->Constructor---->ctrl+A---->ok--->将所有的属性进行构造方法赋值
public Student(String name, int age, String sex, String username) {//"赵又廷",25,"男","小赵"
this.name = name;
this.age = age;
this.sex = sex;
this.username = username;
}
//对外公共的setXXX()/getXXX()
//alt+fn+ins--->getter and Setter ---->ctrl+A---->ok
public String getName() {
return name; //"高圆圆"
}
public void setName(String name) { //"高圆圆"
this.name = name; //this.name="高圆圆"
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
//学习JavaSE,会玩lol
public void studyJavaSE(){
System.out.println(name+"正在学习JavaSE之面向对象") ;
}
public void playLol(){
System.out.println(name+"学习困了就会晚上两把lol") ;
}
}
2 其他知识点补充
2.1 static关键字及应用
static关键字的特点:
- 1)被静态修饰的随着类的加载而加载,优先于对象存在;
- 2)不能和this共存;
- 3)本身含义就是共享,共用;可以多个对象共享共用;
- 这也是告诉我们,什么将某个属性定义static
- 举例: 饮水机的水----共享,共用
- 自己水杯中的水—不行的
- 或者说:三个窗口同时出售100张电影票, 100张票被三个窗口共用;
- 4)被静态修饰的成员变量或者成员方法(静态变量/静态方法) (掌握)
- 访问的方式: 可以使用对象名来访问
- 但是,对于系统来说(jvm)静态的东西:变量/方法都是类名直接访问;
- 类名.变量名;
- 类名.方法名()
- 上次用的java.lang.Math
public static double random() Math.random() ; - 静态的使用场景适用于范围:(记忆的)
- 简单记忆:静态只能访问静态;
- 静态方法中只能访问静态变量
- 静态方法只能调用静态方法;
- 非静态方法皆可以访问静态的东西也可以访问非静态的东西;
2.2 javadoc指令(产生文档说明书:类似于api) (了解)
制作文档说明---->写个工月类写个方法加入文档注释通过javadoc产生文档说明书
- 需求:
- 这一个测试类ArrayTest,有一个数组,静态初始化了,定义一个功能,
- 将数组遍历出来;
- 对ArrayTool.java文件产生一个文档说明书—类似于API(Application Programming Interface:应用程序接口文档)
- 使用jdk安装目录里面的bin里面: javadoc.exe 指令 产生文档说书的指令
- 1)将ArrayTool这个java文件代码复制到本地某个磁盘上,类名和文件名称一致(先不要把package复制上去)
- 2)打开dos窗口,进入到这个java文件的路径下 (找到这个java文件后,这个类权限保证访问权限足够大:public)
- 3)会用javadoc -d 目录名称 -author -version ArrayTool.java(java源文件带后缀) 产生文档说明书
/**
*ArrayTool类是针对数组操作的工具类,里面包含了数组的遍历功能,求数组最值问题,
* 获取数组的元素第一次出现索引值,冒泡排序等提供很多功能;
* @author zhangruonan
* @version V1.0
*/
public class Student {
/**
* 这是无参构造
*/
public Student (){
}
/**
* 这个方法是针对数组的遍历功能,将数组按照指定格式输出,输出格式如下:
* [元素1, 元素2, 元素3, 元素4,....元素n]
* @param arr 要传递的真实数组(要遍历的数组对象)
*/
public static void printArray(int[] arr){ //形式参数---引用类型,数组类型,需要传递这个数组的对象
System.out.print("[");
for(int x = 0 ; x <arr.length ; x ++){
//如果x角标取到最大索引值
if(x==arr.length-1){
System.out.println(arr[x]+"]");
}else{
System.out.print(arr[x]+", ");
}
}
}
/**
* 这个方法是获取数组中的最大值;
* @param arr 要传递数组对象,在这里面查询最大值
* @return 返回数组中的最大值
*/
public static int getMax(int[] arr){
//参照物
int max = arr[0] ;
for(int x =1; x <arr.length ;x++){
if(arr[x]>max){
max = arr[x] ;
}
}
return max ;
}
/**
* 这个方法是获取数组中第一次出现索引值
* @param arr 要查询的数组
* @param key 要查找在数组中的指定的元素
* @return 返回的就是数组的元素第一次出现的索引值,否则,返回-1
*/
public static int getIndex(int[] arr,int key){
//假设
int index = -1 ;
//遍历数组
for(int x = 0 ; x <arr.length ; x ++){
if(key == arr[x]){
index = x ;
break ;
}
}
return index ;
}
/**
* 这个方法是对数组进行冒泡排序
* @param arr 要将数组进行排序
*/
public static void bubleSort(int[] arr){
for(int x = 0 ; x < arr.length -1 ; x ++){
for(int y = 0; y < arr.length-1-x; y++){
if(arr[y] >arr[y+1]){
//互换
int temp = arr[y] ;
arr[y] = arr[y+1] ;
arr[y+1] = temp ;
}
}
}
}
}
根据上面代码生成的文档说明书
2.3代码块(掌握构造代码块,构造方法,静态代码块的
- 局部代码块:比较简单(定义变量超过这个范围访问不了}
- 构造代码块
- 静态代码块
- 构造方法
- 这种代码场景:般出现在 笔试题给你段代码看程序写结果
代码块: 使用{}括起来的内容
- 分类:
- 局部代码块,就是在方法定义中使用{}
- {},作用:就是限定局部变量的生命周期;
- 构造代码块:—在类的成员位置定义的{},它有特点:在执行构造方法之前,如果类中有构造代码块,
- 优先执行构造代码块 作用:也可以给类的成员的数据进行初始化; (实际开发很少见到构造代码块)
- 只要执行构造方法,如果存在构代码块,它必须优先执行,然后才是构造方法…
- 静态代码块:
- 类就加载一次,静态代码块也就执行一次!
格式:
static{ --->跟静态相关的都和类有关系,随着类的加载而加载;
里面书写代码
}
- 静态代码块,构造方法,构造代码块
- 优先级:静态代码块 > 构造代码块> 构造方法,而且每次执行构造方法之前,优先执行所有的构造构造代码块
3 继承(面向对象的第二特征:重点)
继承的概念关键字: extends
继承:
- 将多个类的共性内容抽取出来,放在一个独立的类中,让这个独立的类和其他类产生一种关系
格式:
class 父类名{
共性内容:姓名,年龄.....
提供公共的访问方法setXXX()/getXXX()
}
class 子类名 extends 父类名{}
继承的好处
- 1)可以提高代码复用性
- 2)可以提高代码的维护性,后期便于维护,针对子类和父类进行维护(子父关系明确)
- 3)类与类产生的继承关系,是后面讲"多态"的前提条件;
关于的注意的问题:
- 1.子类继承父类,对于非私有的成员,直接可以继承过来,但是如果私有成员,它可以通过公共的访问可以访问,但是直接访问的;
- 2.被私有修饰的东西(成员变量/成员方法),只能在当前类访问的;
继承的特点:
- 1)在Java语言中,类和的类的关系是一种继承关系,这个继承只能支持"单继承",不支持多继承
- class 父{}
- class 父2{}
- class 子 extends 父,父2{} 多继承:不支持
- class 子 extends 父{} :正常的语法格式
- 2)类和类关系,虽然不支持多继承,但是层层单继承----> 多层继承
在继承关系中,构造方法的访问问题(重点)
- 子类继承父类,子类的所有构造方法都默认访问父类的无参构造方法
- 为什么?子类继承父类,会用到父类的数据,需要让父类先进行初始化; 一个类初始化的—肯定需要执行构造方法的
- 面试题:
- 如果一个父类存在有参构造方法,没有无参构造方法,子类的所有构造会出现什么问题?出现了问题,怎么解决?
- 子类的所有全部构造方法报错,为什么? 子类继承父类,子类的所有构造方法都默认访问父类的无参构造方法
- 方案1:
- 1)手动给出无参构造方法
- 2)假设,人家现在就不需要让你给出父类的无参构造方法;
- 就需要让子类的构造方法,显示的访问父类的有参构造方法 ----要使用关键字 super:代表父类空间标识(代表的父类对象的地址值引用!)
- super() :访问父类的无参构造方法
- super(xxx) :访问父类的有参构造方法
- 这些super一定是在子类构造方法中的第一句话
- 方案2) 保证子类的所有的构造方法某一个构造方法,让父类初始化完毕即可;
- 先通过子类的无参构造方法里面—this(xxx):访问本类(子类)有参构造方法
- 在子类的有参构造方法的第一话:让父类初始化 super(xxx):间接访问父类的有参构造方法
- 子类继承父类,一定要先执行父类的构造方法,初始化完毕之后;然后才能执行子类的构造方法—分层初始化
继承由来: 将多个类的共性内容抽取出来,放在一个独立的类中,让这个独立的类和其他类产生一种关系 “继承”—关键字 extends 格式: class 父类名{ 共性内容:姓名,年龄… 提供公共的访问方法setXXX()/getXXX() } class 子类名 extends 父类名{}
- 在Java中有一个开发原则 “低耦合,高内聚”(以后所有的Java设计模式都需要遵循这一个原则)
- 耦合性:开发中是永远避免不了,可以降低(耦合:类和类的关系)
- 内聚性:指的是某个类完成某个功能的一种能力; 尽量不要产生继承关系来完成一个功能,一个类能完成一个类完成;
- 低耦合:降低耦合性,减少类和类的关系;
3.1 this和super的区别
- this:代表的当前类对象的地址值引用
- super:代表的父类的空间标识(父类的对象的地址值引用)
- this.变量名 :访问本类的成员变量
- super.变量名:访问的父类的成员变量
- this.方法名():访问本类的成员方法
- super.方法名():访问父类的成员方法
- this():访问本类无参构造方法
- this(xxx):访问的是本类的有参构造方法
- super():访问父类的无参构造方法
- super(xxx):访问的父类的有参构造方法
3.2 继承中成员变量的关系问题
- 情况1: 子类和父类的中成员变量名称不一致,访问比较简单,分别访问即可!
- 情况2:子类和父类的成员变量名称一致: 如何访问呢?
- 1)先在子类的局部位置找,有没有这个变量,有就使用;
- 2)如果没有,在子类成员位置中找,有没有这个变量,有就使用;
- 3)如果子类的成员位置也没有,然后会在父类的成员位置找,有没有这个变量,有就使用;
- 4)如果父类的成员位置都没有,报错(前提:这个父类没有它的父类了),说明整个子父类中都没有变量;遵循"就近原则"
3.3 继承中成员方法的关系问题
情况1:子类和父类的成员方法名称不一致,比较简单,分别调用即可;
情况2:子类和父类的成员方法一模一样:权限修饰符,返回值类型,参数列表都一样
类加载的时候,内存是很快的 继承关系
- 父类和子类更静态相关的先执行
- 静态的东西优先于对象存在 (类名 对象名 = new 类名() 😉
- 静态代码块>构造代码块>构造方法…
- 继承关系:分层初始化---->先父类初始化----然后才是子类初始化
3.4 方法重写
3.4.1 final关键字特点:
本身的含义:最终的,无法更改的
-
1)final可以修饰类,该类不能被继承
-
2)final可以修饰变量,此时这个变量是一个"常量",常驻内存;
-
3)final修饰成员方法,此时这个方法不能被子类重写,目的为了保证方法中某些数据的 安全性!
-
final:最终的,无法更改的,状态修饰符 ,被final修饰的成员方法,不能被重写,保证父类的方法安全性!
方法重写:出现在继承中, 描述的子类继承父类的时候,可能沿用父亲的功能,而且使用自己的功能,将父类的功能进行覆盖(复写/重写); 为了让子类具体体现出来的功能信息
举例
动物类 :eat()---->动物饿了都需要吃饭
猫类和狗类:----将eat()方法重写,只有看到具体的动物,才能知道具体吃什么,应该在子类具体体现,将父类的eat重写;
4 多态
4.1 什么是多态,多态的前提条件以及多态的成员访问特点(重点)
猫和狗的多态版—>测试类中代码书写格式 多态:
宏观角度:(现实生活中):一个事物在不同时刻体现的不同形态;
微观角度:(内存中变化):具体对象在内存中的变化(对象在不同时刻的类型)
多态的前提条件(重点)
1)必须有继承关系(类与类),没有继承关系,不谈多态;
2)必须存在方法重写,子类部分功能要父类的功能进行覆盖,重写,子类使用自己的功能体现;
3)必须存在父类引用指向,子类对象
固定格式:
Fu fu = new Zi();
多态的成员访问特点:—>很重要 父类名 对象名 = new 子类名();
1)成员变量
编译看左;运行看左
2)成员方法(存在重写) – 非静态
编译看左,运行看右
静态的—>编译看左;运行看左–>推荐使用类名访问
3)构造方法(多态的前提条件,有继承关系,跟继承一样, 分层初始化先执行父类的构造方法,然后再是子类的构造方法)
4.2 静态变量和成员变量的区别
- 1)在内存中的位置不样
静态变----方法区中的静态区
成员变量—堆内存中的 - 2)切始化不同的
萨态变—限类相关的称为类成员;初始化远远早于对象的创建
成员交量–眼对象有X,将对象创建出来类名对象名=new 类名0;才进行初始化 - 3)访问方式不同
静态变量:访问方式:推荐类名变量名:
成员变量:推荐使用对象名.变量名: - 4)生命周期:
静态变量:随着类的加载而加载随着类的加载而完毕类加载 次静态的东西执行一次静态代码块)
成员变量:随着对象的创建而存在随着对象的创建完毕等得垃圾回收器回收而消失
4.3 多态的弊端是什么?如何解决
不能访问子类的特有功能 解决方案: 向下转型解决子类特有功能的访问
4.4 多态的好处是什么
1)可以提高代码的复用性,由继承保证
2)可以提高代码的扩展性,由多态保证(父类引用指向子类对象)
方法的形式参数传递的是一个引用类型(存在子父关系)一定会使用父类型,调用方法的时候文际参数传递这个父类的子类对象
3)方法的返回做问题:返回的父类型—需要父类的子类对象
4.5 如果在使用多态时出现ClassCastException,说明什么?
类交换异常,说明要把俩个不是一个具体的东西画等号;
使用多态操作向下转型的时候(使用不当堆内存中信息和线内存信息没有子父关系)
4.6 什么是抽象类?抽象类的成员特点?抽象类如何实例化
有抽象方法(在具体的事物中才能能具体的行为)的类定是抽象类:
抽象类的成员特点:
成员变量:可以是变量也是自定义常量
成员方法:可以存在抽象方法也可以存在非抽象方法
构造方法:可以存在无参有参构造方法
抽象类不能实例化:不能new对象
5 什么是接口?接口和子实现类的关系是什么?格式写法
什么是接口?
- 接口体现的是事物的一种额外功能 ;
格式的写法:
interface 接口名{ //命名规范和类名命名一样,见名知意 "大驼峰命名法"
只能为抽象方法
}
接口的子类----"子实现类"
class 子类名 implements 接口名{
}//接口比抽象类还抽象---->特点:不能实例化
5.1 接口的成员特点
构造方法:接口没有构造方法 关于面向对象中牵扯关系问题: Java中最基 本的单元是类
类和类:继承关系extends,Jova语言中只支持单继承,不支持多继承,但是可以多层继承
类和接口:实现关系implements;一个类继承另一个类的同时,可以实现多个接口
按口和接口:继承关系:extends不仅支持单继承,也可以多继承
5.2 接口和抽象类的区别(面试题)jvm的内存调优
1)成员的区别
成员变量:
抽象类: 可以是变量,也可以是自定义常量
接口:成员变量只能是常量,存在默认修饰符,public static final修饰的
成员方法:
抽象类:可以是抽象方法也可以是非抽象方法
接口:只能是抽象方法,存在默认修饰符,public abstract:可以省略构造方法;
构造方法:
抽象类:既可以存在无参构造方法/有参构造方法.存在继承关系,分层初始化,父类初始化,在是子类初始化;(子类需要用到父类中)
接口:没有构造方法的意义:就是通过接7不露给外面功能实现这些功能接口
2)关系区别 Java中最基本的单元是类Java本身就面向接口编程 类和类:继承关系extends, Java语;中只支持单继承不支持多继承但是可以多层继承
类和接口:实现关系implements;一个类继承另个类的同时,可以实现多个按口 接口和接口:继承关系:extends
不仅支持单继承也可以多继承!
3)设计理念的区别
抽象类: 存在继承关系休现的是一种"is a "的关系,什么是什么的一种 A类是B类的一种B类是A类的种,这个时候要使用继承:
接口: 子实现类实现关系体现的一种"like a"的关系什么像什么的种 颜外的打展功能,
5.3 abstract不能和哪些关键字使用
private
static
final
抽象类不能实例化而且它是强制子类必须重写抽象方法:
abstract不能和static使用:
static被类名访问跟类相关静态方法草不上方法重写;
不能和Iprivate使用:
被private修饰的:只能在当前类访问
而abstract修饰的方法需要被子类重写
不能final使用
被final修饰的成员方法,不能被重写: (有的jk源码中会看勁
abstract修饰的方法必须子类重写
综合运用
接口,抽象类封装继…
运动员和教练
蓝球运动员和乒乓球运动员
蓝球教练和乒乓球教练工
跟丘乓球相关的人员为了出国学习英语使用面向对象编程方式测试其体的运动员
教练
自己分析属性和专物的行为
//说英语的接口
interface StudyEnglish {
void speakEnglish();
}
//教练的抽象类
public abstract class JL extends YdPerson{
public JL() {
}
public JL(String name, int age) {
super(name, age);
}
public abstract void tChang();
}
//运动员类的抽象类
public abstract class Ydy extends YdPerson{
public Ydy() {
}
public Ydy(String name, int age) {
super(name, age);
}
public abstract void study();
}
//运动的人类
public class YdPerson {
private String name;//姓名
private int age;//年龄
public YdPerson() {
}
public YdPerson(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
//篮球教练也继承了教练类
public class JLianLq extends JL{
public JLianLq() {
}
public JLianLq(String name, int age) {
super(name, age);
}
@Override
public void tChang() {
System.out.println("我会教篮球");
}
public void play(){
System.out.println("我拿过西安市国家队总冠军");
}
}
//乒乓球教练继承了教练类,实现学习英语的接口
public class JLianPp extends JL implements StudyEnglish{
public JLianPp() {
}
public JLianPp(String name, int age) {
super(name, age);
}
@Override
public void tChang() {
System.out.println("我会交乒乓球");
}
public void play(){
System.out.println("我是世界单打冠军");
}
@Override
public void speakEnglish() {
System.out.println("学英语太难了,一把老骨头还是学会了");
}
}
//乒乓球运动员继承了乒乓球教练类
public class Pp extends JLianPp {
@Override
public void speakEnglish() {
System.out.println("我会说英语了");
}
public Pp() {
}
public Pp(String name, int age) {
super(name, age);
}
@Override
public void tChang() {
System.out.println("我学会了打乒乓球");
}
@Override
public void play() {
System.out.println("我拿到了西安市乒乓球单打冠军");
}
}
//篮球运动员类继承了篮球教练类
public class Lq extends JLianLq{
public Lq() {
}
public Lq(String name, int age) {
super(name, age);
}
@Override
public void tChang() {
System.out.println("我学会了打篮球");
}
@Override
public void play() {
System.out.println("我拿到了西安市第99名");
}
}
//测试类
public class Test {
public static void main(String[] args) {
JLianPp pp = new Pp();
pp.setName("林丹");
pp.setAge(30);
System.out.println(pp.getName()+"---"+pp.getAge());
pp.speakEnglish();
Pp pp1 = (Pp) pp;
pp1.setName("章若楠");
pp1.setAge(22);
System.out.println(pp1.getName()+"---"+pp1.getAge());
pp1.tChang();
pp1.play();
pp1.speakEnglish();
JLianLq lq = new Lq("高圆圆",23);
System.out.println(pp1.getName()+"---"+pp1.getAge());
lq.tChang();
lq.play();
}
}
6 编程练习(接口)
1:需求:鸟和飞机都能飞行,使用代码写一个方法完成鸟的子类比如鹰,麻雀的飞行,还有飞机的飞行
提示:写一个飞的接口
写一个父类鸟,实现接口飞的行为
写具体的鸟的子类,该类继承鸟类
写一个飞机的类,实现飞的接口
//飞的接口
interface fei {
void fly();
}
//鸟类
public class Bread implements fei{
@Override
public void fly() {
System.out.println("飞行");
}
}
//飞机类
public class Plane implements fei{
@Override
public void fly() {
System.out.println("飞机按照规定的航线飞行");
}
}
//鸟的具体实现 鹰类
public class Ying extends Bread{
@Override
public void fly() {
System.out.println("鹰在天空中自由自在的飞");
}
}
//测试类
public class Test {
public static void main(String[] args) {
fei f = new Plane();
f.fly();
Ying ying = new Ying();
ying.fly();
}
}
//运行结果
//飞机按照规定的航线飞行
//鹰在天空中自由自在的飞
2:笔记本电脑(laptop)通常具备使用USB设备的功能。
在生产时,笔记本都预留了可以插入USB设备的USB接口, 但具体是什么USB设备,笔记本厂商并不关心,
只要符合USB规格的设备都可以。
定义USB接口,具备最基本的开启功能和关闭功能。
鼠标和键盘要想能在电脑上使用,那么鼠标和键盘也必须遵守 USB规范,实现USB接口,
否则鼠标和键盘的生产出来也无法使用。(使用面向对象思想编程:接口,多态等)
//usb接口,有俩个方法,一个方法用于提示插入一个提示拔出
interface USB {
void on();//提示开启
void off();//提示关闭
}
//计算机类
public class Laptop implements USB {
@Override
public void on() {
System.out.println("插入设备");
}
@Override
public void off() {
System.out.println("拔出设备");
}
}
//键盘类
public class JianPan extends Laptop{
//实现接口的插入功能
@Override
public void on() {
System.out.println("插入键盘");
}
//实现接口的具体拔出功能
@Override
public void off() {
System.out.println("拔出键盘");
}
}
//鼠标类
public class SuBiao extends Laptop{
//实现接口的插入功能
@Override
public void on() {
System.out.println("插入鼠标");
}
//实现接口的具体拔出功能
@Override
public void off() {
System.out.println("拔出鼠标");
}
}
//测试类
public class Test {
public static void main(String[] args) {
//在电脑上测试鼠标的插入拔出
Laptop laptop = new SuBiao();
laptop.on();
laptop.off();
//在电脑上测试键盘的插入拔出
laptop = new JianPan();
laptop.on();
laptop.off();
}
}
4.创建一个Animal动物类,要求有方法eat()方法,方法输出一条语句“吃东西”。
创建一个接口A,接口里有一个抽象方法fly()。
创建一个Bird类继承Animal类并实现 接口A里的方法输出一条有语句“鸟儿飞翔”,重写eat()方法输出一条语句“鸟儿 吃虫”。
在Test类中向上转型创建b对象,调用eat方法。然后向下转型调用eat()方 法、fly()方法。
//接口类,具有方法fly()
interface A {
void fly();
}
//动物类
public class Animal {
public void eat(){
System.out.println("吃东西");
}
}
//鸟类继承了动物类,实现了接口fly
public class Bread extends Animal implements A{
@Override
public void fly() {//接口方法
System.out.println("鸟儿飞翔");
}
@Override
public void eat() {//重写方法
System.out.println("鸟儿吃虫");
}
}
//测试类
public class Test {
public static void main(String[] args) {
//创建对象,b,,向上转型
Animal b = new Bread();
b.eat();//调用方法eat
//向下转型
Bread bread= (Bread) b;
bread.eat();//调用方法eat
bread.fly();//调用方法fly
}
}
本周的内容先写到这里,完了要是还缺少什么我在补上,有不足的地方可以评论出来我继续改,谢谢支持!