Java之路 - 抽象类、接口、多态、向上向下转型
2021-02-18 03:18
标签:变量 多少 技术 判断 remove nts off size def 注意事项: 1. 抽象类不能创建对象,如果创建,编译无法通过而报错。只能创建其非抽象子类的对象。 群主发普通红包。某群有多名成员,群主给成员发普通红包。普通红包的规则: 注意事项: (1)接口当中的抽象方法,修饰符必须是固定的两个关键字:public abstract (2)这两个关键字修饰符,可以选择性的省略 (3)方法的三要素可以随意定义 (1)接口不能直接使用,必须有一个‘’实现类‘’来实现该接口 格式: 实现类:public class 实现类名称 implements 接口名称}{ //..... } (2)接口的实现类必须覆盖重写(实现)接口中的所有抽象方法 去掉abstract关键字,加上方法体大括号 (3)创建实现类的对象,进行使用 多态的使用: 13.接口多态的综合案例 进行描述笔记本类,实现笔记本使用USB鼠标、USB键盘 Java之路 - 抽象类、接口、多态、向上向下转型 标签:变量 多少 技术 判断 remove nts off size def 原文地址:https://www.cnblogs.com/caixiaowu/p/12681477.html1.抽象类
如果父类当中的方法不确定如何进行{}方法实现,那么这就是一个抽象方法
抽象方法所在的类必须是抽象类
使用方法:
(1)不能直接创建new抽象类对象
(2)必须用一个子类来继承抽象父类
(3)子类必须覆盖重写抽象父类当中所有的抽象方法
覆盖重写(实现):去掉抽象方法的abstract关键字,然后补上方法体大括号;
(4)创建子类对象进行使用
public abstract class animal { //抽象类
public abstract void eat(); //这是一个抽象方法
public void nomalMethod(){
}
}
理解:假设创建了抽象类的对象,调用抽象的方法,而抽象方法没有具体的方法体,没有意义。
2. 抽象类中,可以有构造方法,是供子类创建对象时,初始化父类成员使用的。
理解:子类的构造方法中,有默认的super(),需要访问父类构造方法。
3. 抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
理解:未包含抽象方法的抽象类,目的就是不想让调用者创建该类对象,通常用于某些特殊的类结构设计。
4. 抽象类的子类,必须重写抽象父类中所有的抽象方法,否则,编译无法通过而报错。除非该子类也是抽象类。
理解:假设不重写所有抽象方法,则类中可能包含抽象方法。那么创建对象后,调用抽象的方法,没有意义。
爷爷、父亲、儿子三类抽象继承关系:爷爷辈;
public abstract class animal { //抽象类
public animal(){
System.out.println("动物类父类构造方法");
}
public abstract void eat(); //这是一个抽象方法
public abstract void sleep();
public void nomalMethod(){
System.out.println("正常方法");
}
}
父亲辈:
public abstract class Cat extends animal {
public Cat(){
System.out.println("猫类构造方法");
}
@Override
public void eat(){
System.out.println("猫吃鱼");
}
}
儿子:
public class CatFei extends Cat {
@Override
public void sleep() {
System.out.println("嘿嘿嘿的睡觉");
}
}
发红包案例:
1. 群主的一笔金额,从群主余额中扣除,平均分成n等份,让成员领取。
2. 成员领取红包后,保存到成员余额中。
请根据描述,完成案例中所有类的定义以及指定类之间的继承关系,并完成发红包的操作。public class PocketUser {
private String name;
private int money; //当前用户的余额
public PocketUser() {
System.out.println("用户的无参构造方法");
}
//显示一下当前用户有多少钱
public void show(){
System.out.println("用户" + name + "剩余" + money + "元");
}
public PocketUser(String name, int money) {
System.out.println("用户的有参构造方法");
this.name = name;
this.money = money;
System.out.println(this.name);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
}
public class PocketManager extends PocketUser {
public PocketManager(){
//super();
System.out.println("管理员的无参构造方法");
}
public PocketManager(String name, int money) {
super(name, money);
System.out.println("管理员的有参构造方法");
}
public ArrayList
public class PocketMember extends PocketUser{
public PocketMember(){};
public PocketMember(String name, int money){
super(name,money);
}
public void receive(ArrayList
public class MainMethod {
public static void main(String[] args) {
PocketManager m1 = new PocketManager("chris",150);
PocketMember one = new PocketMember("joe",5);
PocketMember two = new PocketMember("lin",10);
PocketMember three = new PocketMember("sea",15);
m1.show();
one.show();
two.show();
three.show();
//群主发红包
ArrayList
2.接口(Interface) 接口就是多个类的公共规范
(1)接口没有构造方法和静态代码块,不能new,只能通过实现类实现
(2)一个类的直接父类是唯一的,但是一个类是可以同时实现多个接口
(3)如果实现类没有覆盖重写其接口的所有抽象方法。那么他一定要是个抽象类
(4)如果实现类实现的多个接口中多个接口的默认方法重复了,那么要对其进行覆盖重写
(5)一个类如果直接父类当中的方法,和接口当中的方法产生了冲突,优先用父类当中的方法
如 public class A extends implements MyInterface 时,如果父类当中的方法和接口当中的默认方法重名了,优先使用父类的而不是接口
接口是一种引用数据类型,最重要的内容就是其中的抽象方法
接口就是一种公共的规范标准,只要符合规范标准,就可以大家通用
接口的格式:
public interface 接口名称{ 接口内容 }
虽然换成了关键字interface 但编译生成的字节码文件依旧是.class
在java8中,接口内容可以包括:
(1)常量
(2)抽象方法
(3)默认方法
(4)静态方法
如果是java9,还可以额外包含有 5. 私有方法
3.接口的使用
接口:
public interface MyInterface {
// 这是抽象方法1
public abstract void methodAbs1();
//这也是抽象方法
void methodAbs2();
}
实现类:
public class MyImpl implements MyInterface {
@Override
public void methodAbs1(){
System.out.println("这是第一个方法体");
}
@Override
public void methodAbs2(){
System.out.println("这是第二个方法体");
}
}
如果实现类并没有覆盖重写接口中所有的抽象方法,那么这个实现类自己必须是抽象类。
4.接口的默认方法定义
格式: public default 返回值类型 方法名称 (参数列表){ 方法体 }
接口当中的默认方法,可以解决接口升级的问题
应用场景:当一个接口已经被投入很久了,而且有抽象方法,现在又添加了一个抽象方法,那么此时已经实现该接口的类不是全都要改了?
答:将其设置会默认方法,此时默认方法会被其实现类继承
注意事项:
1.接口的默认方法可以被实现类直接调用
2.接口的默认方法也可以被其实现类覆盖重写
5.接口的静态方法 当对象与对象直接有共有的特点时,或者一样的方法,那么就与类有关
格式:public static 返回值类型 (参数列表){ 方法体 }
注意!!!! 不能通过接口实现类的对象来调用接口当中的静态方法!!! 只能通过接口名称来调用其静态方法
6.接口的私有方法
当两个方法体直接有太多重复代码,此时需要把重复的抽取出来,抽取一个公共方法来解决两个默认方法之间重复代码的问题
但是这个共有方法不应该让实现类使用,应该是内部私有化的。从java9开始,接口当中允许定义私有方法
(1)普通私有方法,解决多个默认方法之间重复代码问题
格式:private 返回值类型 方法名称 (参数列表){ 方法体 }
(2)静态私有方法,解决多个静态方法之间重复代码问题
格式:private static 返回值类型 方法名称(参数列表){方法体}
public interface MyInterface {
public default void defaultMethod1(){
System.out.println("这是新添加的默认方法1");
// System.out.println("AAA");
// System.out.println("BBB");
methodCommon();
}
public default void defaultMethod2(){
System.out.println("这是新添加的默认方法2");
// System.out.println("AAA"); //重复代码
// System.out.println("BBB"); //重复代码
methodCommon();
}
private void methodCommon(){
System.out.println("AAA");
System.out.println("BBB");
}
}
7.接口的常量
接口当中也可以定义“成员变量”,但是必须使用public static final 三个关键字进行修饰
从效果上看这其实就是接口的常量了
1.格式:public static final 数据类型 常量名称 = 数据值; 一旦赋值不可修改 一旦使用final关键字进行修饰,所以不可变
接口当中的常量,可以省略public static final, 但其实它还是不可变的,默认存在
2.接口当中的常量,必须进行赋值,不能不赋值,必须手动进行赋值
3.接口常量中的名称,使用完全大写的字母,用下划线进行分隔
public static final int NUM_OF_MY_CLASS = 6;
8.接口内容小结
9.类与接口的关系
(1)类与类之间是单继承的
(2)类与接口之间是多实现的
(3)接口与接口之间是多继承的
如果多个父接口当中的默认方法重复,那么子接口必须进行默认方法的覆盖重写,而且要带着default!不能删除
10.多态(Polymorphism)
extends继承和implements实现,是多态性的前提
格式:父类名称 对象名 = new 子类名称(); 或者 接口名称 对象名 = new 实现类名称(); 左父右子
访问成员变量的两种方式:口诀:编译看左边,运行看左边
(1)直接通过对象名称访问,看等号左边是谁,优先用谁,没有则向上找,不会找右侧的子类!!!
(2)直接通过成员方法访问,看该方法属于谁,优先用谁,没有则向上找,子类没有覆盖重写就是父类中找,如果子类覆盖重写了,就从子类中找
访问成员方法的规则:口诀:编译看左边,运行看右边
new的是谁,就优先用谁,没有则向上找
父类:
public class Fu {
int num = 10;
public Fu(){
System.out.println("父类无参构造");
}
public Fu(int num){
System.out.println("父类you参构造");
}
public void fumethod(){
System.out.println("父类方法执行");
}
public void method(){
System.out.println("父类重名方法执行");
int fu = 222;
fumethod();
}
}
子类:
public class Zi extends Fu{
int num = 20;
public Zi(){
this(12);
System.out.println("子类无参构造");
}
public Zi(int num){
System.out.println("子类有参构造");
}
public void ziMethod(){
int num = 30;
System.out.println("子类方法执行");
System.out.println(num); //输出的是局部变量num = 30
System.out.println(this.num); //输出的是成员变量 num = 20
System.out.println(super.num); //输出的是父类的成员变量 num = 10
// super.method();
}
@Override
public void method() {
super.method();
}
}
main方法:
public class InterfaceMain {
public static void main(String[] args) {
//多态的使用
Fu obj = new Zi();
obj.method();
obj.fumethod();
Zi zi = (Zi) obj;
zi.fumethod();
System.out.println(obj instanceof Zi);
}
}
使用多态的好处:!!!!
11.对象的向上转型,就是多态写法
含义:右侧创建一个子类对象,把它当做父类来看待使用 就是左父右子
注意事项:向上转型一定是安全的,从小范围转换为大范围,有一个弊端,子类的特有方法无法使用
解决方案:用对象的向下转型【还原】 一定要进行类型判断 instanceof
格式:子类 新的对象名 = (子类名称) 原本的对象名; 含义:将父类对象还原为原来的子类对象
注意事项:原本的对象必须是new的子类对象 如 原本是 animal animal = new Cat();应该这样转 Cat(原本右侧new的类) cat(新的对象名) = (Cat) animal;
如果不遵守,而是转成狗类,则会报 java.lang.ClassCastException
12.instanceof 子类也是一个父类!!
如何才能查看原本父类指向的子类是谁呢? - - instanceof 来判断
格式: 对象 instanceof 类名称 会返回一个boolean值
animal instance of Cat
public class InterfaceMain {
public static void main(String[] args) {
Zi zi = new Zi();
give(zi);
}
public static void give(Fu fu){
System.out.println("来啦");
}
}
- - - - 笔记本电脑
笔记本电脑(laptop)通常具备使用USB设备的功能。在生产时,笔记本都预留了可以插入USB设备的USB接口,
但具体是什么USB设备,笔记本厂商并不关心,只要符合USB规格的设备都可以。
定义USB接口,具备最基本的开启功能和关闭功能。鼠标和键盘要想能在电脑上使用,那么鼠标和键盘也必须遵守
USB规范,实现USB接口,否则鼠标和键盘的生产出来也无法使用。
案例分析:
(1)USB接口,包含开启功能、关闭功能
(2)笔记本类,包含运行功能、关机功能、使用USB设备功能
(3)鼠标类,要实现USB接口,并具备点击的方法
(4)键盘类,要实现USB接口,具备敲击的方法public interface USB {
public abstract void open();
public abstract void close();
}
public class Mouse implements USB {
@Override
public void open() {
System.out.println("鼠标已连接,可以正常使用");
}
@Override
public void close() {
System.out.println("鼠标已关闭");
}
public void kick(){
System.out.println("鼠标点击使用");
}
}
public class Keyboard implements USB{
@Override
public void open() {
System.out.println("键盘已连接,可以正常使用");
}
@Override
public void close() {
System.out.println("键盘已断开");
}
public void press(){
System.out.println("键盘输入单词");
}
}
public class MyLaptop {
private String user;
public MyLaptop() {}
public MyLaptop(String user) {
this.user = user;
System.out.println("用户" + user +"正在使用电脑");
}
public void powerOff(USB usb1,USB usb2){
System.out.println("笔记本正在关机");
usb1.close();
usb2.close();
}
public void powerOn(){
System.out.println("笔记本正在开机");
}
public void useDevice(USB usb){
if (usb instanceof Mouse){
System.out.println("这是鼠标设备,使用鼠标设备");
Mouse mouse = (Mouse) usb; //因为不确定传进来的usb设备是鼠标还是键盘,确定后要向下转型
mouse.kick();
} else if(usb instanceof Keyboard){
System.out.println("这是键盘,使用键盘");
Keyboard keyboard = (Keyboard) usb;
keyboard.press();
}
}
}
public class UseLaptop {
public static void main(String[] args) {
USB mouse = new Mouse();
USB keyboard = new Keyboard();
MyLaptop computer = new MyLaptop("蔡晓武");
computer.powerOn();
computer.useDevice(mouse);
computer.useDevice(keyboard);
computer.powerOff(mouse,keyboard);
}
}
文章标题:Java之路 - 抽象类、接口、多态、向上向下转型
文章链接:http://soscw.com/index.php/essay/56861.html