Java学习日志Day12_抽象类_方法重写_接口_接口、抽象类、多态综合问题

本文详细探讨了Java中的抽象类、方法重写、接口及其相关概念。强调了抽象类的主要用途是阻止实例化,并指出抽象方法与private、static、final关键字的冲突。接着阐述了方法重写时需注意的访问权限问题。对于接口,解释了其作为扩展性的体现,以及接口与类、抽象类的区别。此外,总结了接口成员的特性,如只能包含常量和抽象方法。最后讨论了类与类、类与接口、接口与接口之间的关系以及抽象类与接口在设计思想上的差异。

一、抽象类注意事项

  1. 问题:
    一个类,没有抽象方法,可不可以将这个类定义为抽象类呢? 意义是什么?
    可以定位抽象类,意义:就是为了这个类不能够实例化!

    一般情况:如果一个类中,没由抽象方法,将它定义为抽象类
    它的实例化: 可以通过它里面的静态功能,静态功能的返回值类型是当前类本身!
    后期:Calendar:日历类 java.util.Calendar;

            Calendar:抽象类
            public static Calendar getInstantce(){
    
                ....
                ....
                ....
                return new GregorianCalendar() ; Calendar的子类
            }
    
  2. 抽象 的关键字:
    abstract不能和哪些关键字使用(冲突)

    abstract可以修饰类,才是这个类不能实例化了,这个类叫抽象类

    abstract可以修饰方法----抽象方法:没有方法体

    和private关键字不能一块使用:被private修饰的只能在本类中访问,外界类中的成员不能访问!
    和static关键字冲突:如果加了静态,子类要重写父类的方法,这种访问方式:
    多态:Fu f = new Zi() ;f.方法名() ;
    静态的方式—>随着类的加载而加载: 类名.方法名();
    和final关键字冲突:被final修饰的方法不能被重写,而abstract抽象方法,要强制子类必须重写,否则子类报错,出现冲突了!

          abstract:和默认修饰符   abstract 返回值类型 方法名(形参列表) ;
    

    和public可以使用
    和protected:
    限定的是子类: 在同一个包下/或者在不同包下 都可以访问

举例:
abstract class Animal{

    //非抽象方法
    public void show(){
        System.out.println("show Animal");
    }
   // protected abstract void eat() ;
     public abstract void eat() ;
     //abstract void eat() ;

    //不行的
    //private abstract void eat() ; //和private冲突
    //public static abstract void eat() ;//和static关键字冲突
   // public final abstract void eat() ;//和final关键字冲突
}
class Cat extends Animal{
    public void show(){
        System.out.println("show Cat");
    }

    @Override
    public void eat() {

    }
}

//测试类
public class AbstractDemo {
    public static void main(String[] args) {
            Animal a = new Cat() ;
            a.show();
    }
}

二、方法重写注意事项

方法重写的注意事项:
子类继承父类,要重写父类的功能的时候,必须要保证子类的方法的访问权限足够大,要么
就父类的权限保持一致即可!

举例:
//父类
class Fu{
  /*  public void show(){
        System.out.println("show Fu");
    }*/

  void show(){
      System.out.println("show Fu");
  }
}
class Zi extends  Fu{

    //不能够访问
    /* void show(){
         System.out.println("show Zi");
     }*/
    public void show() {
        System.out.println("show Zi");
    }
}

//测试类
public class OverrideDemo {
    public static void main(String[] args) {
            Fu fu = new Zi() ;
            fu.show() ;
    }
}

三、接口

  1. 什么是接口?
    接口是比抽象类还抽象的事物,它体现的一种 “扩展性”— 事物的额外功能!
    如果一些具体事物能够将额外功能实现了,那么这些具体事物就应该具备这些功能了!
    接口:体现的是一种 "like a"的关系
    跳高猫—>类似猫

  2. 定义格式:

            	interface 接口名{  				//接口名要见名知意---符号"标识符的规则"
            }
    
  3. 接口中的方法:只能是抽象方法

  4. 接口特点:不能实例化:不能new

    将接口的子类称为"子实现类"
    可以是抽象类, 一定会有抽象类的具体的子类,否则没有意义!
    也可以是具体类 : 通过具体类实例化

              	接口名 对象名 = new 子实现类名() ;
    

    子实现类和接口之间的关系:实现关系 :implements

       			class 子实现类名 implements 接口名{
       }
    
举例:
//定义一个跳高的接口
interface  Jump{
      public abstract String jump() ;
}

//猫类
//abstract  class Cat implements  Jump { //类与接口的关系;实现关系
class Cat implements  Jump { //类与接口的关系;实现关系
    public void eat(){
        System.out.println("猫吃鱼");
    }
    public void catchMouse(){
        System.out.println("猫抓老鼠...");
    }

    @Override
    public String jump() {
        return "猫可以跳高了" ;
    }
}
//测试类
public class InterfaceDemo {
    public static void main(String[] args) {
        //Jump jump = new Jump() ;//不能实例化
      //  Jump jump = new Cat() ; //不能实例化  :Cat是抽象类

        //Cat如果是具体类
        Jump jump = new Cat() ;  ////接口多态: (使用的 最多的)   向上转型
        String str = jump.jump();// 使用的 接口(就是一个abstracct)的
        System.out.println(str);

     //   jump.eat() ;
        Cat c = (Cat)jump ;//向下转型
        c.eat();
        c.catchMouse() ;
    }
}

四、接口中的成员特点

成员变量:只能是常量:存在默认修饰符:public static final … :可以省略不写
构造方法:无
成员方法:只能是抽象方法:存在默认修饰符:public abstract :可以省略不写
开发中,定义了一个接口
子实现类名都是在接口名的后面加上Impl

举例:
//定义一个接口
interface  Inter{

   /* public Inter(){

    }*/
    //成员变量
    int num = 100 ;
    final int num2 = 200 ;
    void show() ;
    //public void method(){}
    public abstract void method() ;

}

//子实现类
class InterImpl implements  Inter{

    @Override
    public void show() {
        System.out.println("show InterImpl");
    }

    @Override
    public void method() {
        System.out.println("method InterImpl");
    }
}

//测试类
public class InterfaceDemo2 {
    public static void main(String[] args) {

        //接口多态的形式
        Inter i = new InterImpl() ;
        System.out.println(i.num);
       // i.num = 200 ; //也是常量 :已经被final修饰(没有明确显示)
        //i.num2 = 300 ;//num2已经final修饰了
        System.out.println(Inter.num); //接口名.变量--->变量: static修饰
        System.out.println(Inter.num2);
        System.out.println("------------------") ;
        i.show();
        i.method();

    }
}

五、类与类,类与接口,接口与接口的区别(抽象类与接口区别)

  1. 类与类,类与接口,接口与接口之间的关系

    类与类之间:继承的关系 extends :支持单继承,不支持多继承,可以多层继承

    类与接口之间:实现关系 implements:
    一个类继承另一个类的同时,可以实现多个接口

    接口与接口之间:继承关系 extends :可以单继承,也可以多继承
    interface 接口名1 extends 父接口1,父接口2,…{}

  2. 抽象类和接口的区别?
    1)成员的区别

     成员变量:
             抽象类:可以是变量,也可以常量(使用final关键字)
             接口:只能是常量:存在默认修饰符:public static final(可以省略不写)
     构造方法
             抽象类: 有构造方法;无参/有参: 针对父类进行分层初始化
                             抽象类多态的形式: 抽象的父类名 对象名 = new 子类名() ;
             接口:没有构造方法
     成员方法:
             抽象类:既可以是抽象方法(必须携带abstract),也可以是非抽象方法
             接口:只能是抽象方法:存在默认修饰符:public abstract
    

2)关系的区别
类与类,类与接口,接口与接口之间的关系

            类与类之间:继承的关系 extends :支持单继承,不支持多继承,可以多层继承
            类与接口之间:实现关系 implements:
                     一个类继承另一个类的同时,可以实现多个接口

            接口与接口之间:继承关系 extends :可以单继承,也可以多继承
                         interface 接口名1 extends 父接口1,父接口2,...{}

3)设计理念的区别

    		抽象类----体现的继承关系(类与类之间的关系居多),---描述 "is a"的关系
    		接口--- 实现关系:一个事物所具备的额外功能,---描述的是一种"like a"的关系
                       使用接口----使用接口多态---可以提高代码的扩展性!

六、综合问题:

举例1package com.qf.test;

class MyClass{
        //静态变量
    static int a;  //随着类的加载而加载:优先于对象进内存   (可以被多个对象共用)  静态区域: 0  100 300
    int b;  //成员变量  :0  200 mc1
            //成员变量:0  400 mc2
}
public class TestMain{
    public static void main(String args[]){
        MyClass mc1 = new MyClass();
        MyClass mc2 = new MyClass();  //新的空间地址
        mc1.a = 100;
        mc1.b = 200;
        mc2.a = 300;
        mc2.b = 400;
        System.out.println(mc1.a);  //300
        System.out.println(mc1.b); //200
        System.out.println(mc2.a); //300
        System.out.println(mc2.b); //400
    }
}
举例2package com.qf.test;

class A {
    public void show() {
        show2();
    }
    public void show2() {
        System.out.println("我");
    }
}
class B extends A {
    /*
    * public void show() {
        show2();
    }
    * */
    public void show2() {
        System.out.println("爱");  //"爱"
    }
}
class C extends B {
    public void show() {
        super.show();
    }
    public void show2() {
        System.out.println("你"); //"你"

    }

}
public class Test {
    public static void main(String[] args) {
        A a = new B(); //多态
        a.show();
        B b = new C();
        b.show();
    }
}
举例3/* 定义榨汁机JuiceMachine 有榨汁方法makeJuice,传入相应的水果。
  		如果传入的是Apple 输出   "流出苹果汁"
         传入的是Orange 输出  "流出橙汁"
  	   传入的是Banana 输出  "流出香蕉酱"
 
  	 分析:
  	    有哪些类,这里类中有哪些方法
  	     JuiceMachine 类
  	                    makeJuice:榨汁方法 ---->可以定义静态/非静态
  	                    makeJuice(Fruit fruit){
  	                        fruit.flow() ;
 
  	                    }
  	     Fruit类 :水果类  --> 抽象类
  	            flow() ---->流出   给出声明即可!
 
  	            Apple
  	            Orange
  	            Banana
  	                        继承自水果类 */
//抽象的水果类
public abstract class Fruit {

    //流出的方法
    public abstract void flow() ;
}

public class Apple extends Fruit {
    @Override
    public void flow() {
        System.out.println("流出苹果汁");
    }
}

public class Orange extends Fruit {
    @Override
    public void flow() {
        System.out.println("流出橙汁");
    }
}

public class Banana extends Fruit {
    @Override
    public void flow() {

        System.out.println("流出香蕉酱");
    }
}

public class JuiceMachine {  //看成工厂类

    //构造私有化
    private JuiceMachine(){}

    //静态功能
    public static void makeJuice(Fruit fruit){
        fruit.flow();
    }

    //非静态的
    //榨汁方法
   /* public void makeJuice(Fruit fruit){ //多态
        fruit.flow();
    }*/
}

public class Test3 {
    public static void main(String[] args) {

        //创建榨汁机类对象
        /*JuiceMachine jm = new JuiceMachine() ;
        Fruit fruit = new Apple() ;//父类引用指向子类对象
        jm.makeJuice(fruit);
        System.out.println("-----------------------");
        fruit = new Orange() ;
        jm.makeJuice(fruit);
        System.out.println("-----------------------");
        fruit = new Banana() ;
        jm.makeJuice(fruit);*/

        Fruit fruit = new Apple() ;
        JuiceMachine.makeJuice(fruit);
        System.out.println("----------------------") ;
        fruit = new Orange() ;
        JuiceMachine.makeJuice(fruit);
        System.out.println("----------------------") ;
        fruit = new Banana() ;
        JuiceMachine.makeJuice(fruit);
    }
}
举例4/**
 雇员类(Employee-抽象类):包含抽象方法work()
 work()方法表示 工作内容
 程序员类和项目经理类都属于雇员
 程序员类:属性(姓名、工号、工资),行为(工作:软件开发)
 项目经理类:属性(姓名、工号、工资、奖金:经理的特有属性),行为(工作:控制进度)

 要求:子类在实现时,用System.out.println()在控制台输出
 例如: 程序员 work() 输出:"软件开发"

 分析:
        程序员,经理: 共有属性:姓名,工号,工资 --->继承自己员工类

            经理的特有属性:奖金
 Employee-抽象类
             姓名,工号,工资
             经理和程序员的工作性质不一样,只能员工类给出声明:抽象方法

 */

public  abstract class Employee {

    //姓名,工号,工资
    private String empName ;
    private String empId ;
    private int empSalary ;

    public Employee() {
    }

    public Employee(String empName, String empId, int empSalary) {
        this.empName = empName;
        this.empId = empId;
        this.empSalary = empSalary;
    }

    public String getEmpName() {
        return empName;
    }

    public void setEmpName(String empName) {
        this.empName = empName;
    }

    public String getEmpId() {
        return empId;
    }

    public void setEmpId(String empId) {
        this.empId = empId;
    }

    public int getEmpSalary() {
        return empSalary;
    }

    public void setEmpSalary(int empSalary) {
        this.empSalary = empSalary;
    }

    //工作: 抽象方法
    public abstract  void work() ;

    public void show(){
        System.out.println("员工的姓名是:"+empName+",工号是:"+empId+"基本工资是:"+empSalary);
    }
}

public class Programmer extends  Employee {

    public Programmer() {
    }

    public Programmer(String empName, String empId, int empSalary) {
        super(empName, empId, empSalary);
    }

    @Override
    public void work() {
        System.out.println("程序员日日夜夜敲代码...");
    }
}

public class Manager extends Employee {
    //特有属性
    //奖金
    private int bouns ;

    public int getBouns() {
        return bouns;
    }

    public void setBouns(int bouns) {
        this.bouns = bouns;
    }

    public Manager() {
    }

    public Manager(String empName, String empId, int empSalary,int bouns) {
        super(empName, empId, empSalary); //先让父类初始化
        this.bouns = bouns ;

    }
    //Employee emp = new Manager() ;
    //emp.setBouns() ;//报错

    @Override
    public void work() {
        System.out.println("经理控制进度");
    }
}

public class EmployeeTest {
    public static void main(String[] args) {

        //程序员类:多态
        Employee emp = new Programmer() ; //方式1
        emp.setEmpName("高圆圆") ;
        emp.setEmpId("9527");
        emp.setEmpSalary(8000);
        emp.show();
        emp.work() ;

        System.out.println("-------------------------");
        //方式2
        emp =  new Programmer("华安","9527",9000) ;
        emp.show();
        emp.work() ;
        System.out.println("-------------------------");
        //测试经理类
        emp = new Manager() ;
        emp.setEmpName("赵又廷");
        emp.setEmpId("9528");
        emp.setEmpSalary(5000);
        emp.show();
        //emp.setBouns() ;
        Manager manager = (Manager)emp; //向下转型
        manager.setBouns(10000) ;
        System.out.println("奖金是"+manager.getBouns());
        System.out.println("-------------------------");
        Manager m = new Manager() ;
        m.setEmpName("张三");
        m.setEmpId("it001");
        m.setEmpSalary(10000);
        m.setBouns(8000);
        System.out.println(m.getEmpName()+"---"+m.getEmpId()+"---"+m.getEmpSalary()+"---"+m.getBouns());
        System.out.println("-------------------------");
         m = new Manager("文章","it002",5000,7000) ;
        System.out.println(m.getEmpName()+"---"+m.getEmpId()+"---"+m.getEmpSalary()+"---"+m.getBouns());

    }
}
```:
```java
/*举例5:
定义一个动物类,里面有一个方法voice(),
  		定义一个类Cat,实现voice方法
  		然后增加一种新的动物类型:Pig(猪),实现voice()方法。
  		定义一个Dog类,实现voice方法;
 
  		定义一个Store(宠物店)类的getInstance方法:
  		如果传入的参数是字符串dog,则返回一个Dog对象;
  		如果传入pig,则返回一个Pig对象;否则,返回一个Cat对象。
 
 		提示:字符串进行判断 通过equals(字符串)方法
 */
 public abstract class Animal {

    //里面有一个方法voice(),
    public abstract  void voice() ;//动物都需要发声
}

public class Cat extends Animal {
    @Override
    public void voice() {
        System.out.println("猫的voice是喵喵喵");
    }
}

public class Dog extends  Animal {
    @Override
    public void voice() {

        System.out.println("狗的voice汪汪汪");
    }
}

public class Pig extends  Animal {
    @Override
    public void voice() {
        System.out.println("猪的voice是哼哼哼");
    }
}

public class Store {

    private Store(){}
    //提供getInstance()--->有返回值  静态的功能
    public static Animal getInstance(String type){
        if(type.equals("dog")){
            return new Dog() ;
        }else if(type.equals("pig")){
            return new Pig() ;
        }else{
            return new Cat() ;
        }
    }
}

public class Test3 {
    public static void main(String[] args) {

        //宠物店调用方法
        //多态的间接使用
        Animal a = Store.getInstance("dog") ;  // Animal a = new Dog() ;
        a.voice();
        System.out.println("---------------------");
        a = Store.getInstance("pig") ;
        a.voice();
        System.out.println("---------------------");
        a = Store.getInstance("monkey") ;
        a.voice();
    }
}
举例6/*
需求:
        有运动员和教练,
        运动员---篮球运动员和乒乓球运动员,教练---篮球教练和乒乓球教练,
        和乒乓球相关的人员为了出国交流,需要学习专业英语,请使用面向对象编程思想设计这个程序!
 
 
      	分析:
 
 
           乒乓球运动员 和篮球运动员                       乒乓球教练和篮球教练
               姓名,年龄,性别                                     姓名,年龄,性别
               学习的功能,                                              teach()
 
           抽取 :运动员 抽象类                           抽取:教练 抽象类
           	姓名,年龄,性别                                        姓名,年龄,性别
           	特有功能                                            特有功能
                   学习:每一种运动员学习不一样,方法声明!            teach();
 
 
            抽取:
                           人 Person类  抽象
                           姓名,年龄,性别
 
                           eat() ;
 
 
              乒乓球教练和乒乓球运动员 学习英语  ----> interface StudyEnghlis{}
*/

结构图如图所示

public abstract class Person {
    private String name ;
    private int age ;
    private String gender ;

    public Person() {

    }

    public Person(String name, int age, String gender) {
        this.name = name;
        this.age = age;
        this.gender = gender;
    }

    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 String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public abstract  String  eat() ;
}

public abstract class Player extends Person {

    public Player() {
    }

    public Player(String name, int age, String gender) {
        super(name, age, gender);
    }

    @Override
    public String eat() {
        return "运动员吃一些营养餐" ;
}

    //定义学的功能
    public abstract  void study() ;
}

public abstract class Coach extends Person {
    public Coach() {
    }

    public Coach(String name, int age, String gender) {
        super(name, age, gender);
    }

    @Override
    public String eat() {
        return "教练吃普通的工作餐" ;
    }

    public abstract  void teach() ;
}

public class PingPangPlayer extends  Player implements StudyEnglish {
    public PingPangPlayer() {
    }

    public PingPangPlayer(String name, int age, String gender) {
        super(name, age, gender);
    }

    @Override
    public void study() {
        System.out.println("学习如何接球和发球...");
    }

    @Override
    public void speakEnglish() {
        System.out.println("可以使用英语交流...");
    }
}

public class PingPangCoach extends Coach implements  StudyEnglish {
    public PingPangCoach() {
    }

    public PingPangCoach(String name, int age, String gender) {
        super(name, age, gender);
    }

    @Override
    public void teach() {
        System.out.println("教授如何接球和发球");
    }

    @Override
    public void speakEnglish() {
        System.out.println("可以使用英语交流");
    }
}

public class BasketBallPlayer extends Player {
    public BasketBallPlayer() {
    }

    public BasketBallPlayer(String name, int age, String gender) {
        super(name, age, gender);
    }

    @Override
    public void study() {
        System.out.println("学习如何运球和投篮");
    }
}

public class BasketBallCoach extends  Coach {
    public BasketBallCoach() {
    }

    public BasketBallCoach(String name, int age, String gender) {
        super(name, age, gender);
    }

    @Override
    public void teach() {

        System.out.println("教授如何运球和投篮以及战术");
    }
}

public interface StudyEnglish {

    public abstract void speakEnglish();
}

public class InterfaceTest {
    public static void main(String[] args) {

        //乒乓球相关的人员的功能比较多a
        //测试乒乓球运动员
        Player player = new PingPangPlayer() ;
        player.setName("张继科");
        player.setAge(26);
        player.setGender("男");

        System.out.println(player.getName()+"---"+player.getAge()+"---"+player.getGender());

        String s = player.eat();
        System.out.println(s);
        player.study();

        //接口多态
        StudyEnglish se = new PingPangPlayer() ;
        se.speakEnglish();
        //有参构造方式:自己测试xxxxxxxxxxxxxxx
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

igfff

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值