抽象类
1.抽象类
1.1抽象类概述
在Java中,一个没有方法体的方法定义为抽象方法,而类中如果有抽象方法,该类必须定义为抽象类。
1.2抽象类的特点
- 
抽象类和抽象方法必须使用abstract关键字修饰 public abstract class 类名{} public abstract void eat(); 
- 
抽象类中不一定有抽象方法,有抽象方法的一定是抽象类 
- 
抽象类不能实例化 抽象类如何实例化呢?参照多态的方式,通过子类对象实例化,这叫抽象类多态 
- 
抽象类的子类: 要么重写抽象类中的所有抽象方法,要么是抽象类。 
package com.szy001;
/*
抽象类
 */
public abstract class Animal {
    //抽象方法
    public abstract void eat();
    public void sleep(){
        System.out.println("睡觉");
    }
}
package com.szy001;
public class Cat extends Animal{//抽象类的子类,它继承了抽象类
    @Override
    public void eat() {//重写了抽象方法
        System.out.println("猫吃鱼");
    }
}
package com.szy001;
public abstract class Dog extends Animal{//抽象类的子类要么重写抽象类中的所有方法,要么它本身也是个抽象类
    //public abstract void eat();
}
package com.szy001;
public class AnimalDemo {
    public static void main(String[] args) {
//    Animal a=new Animal();//抽象类不能直接实例化
        Animal a=new Cat();//抽象类可以通过子类对象实例化
        a.eat();
        a.sleep();
    }
}
1.3抽象类的成员特点
- 
成员变量 可以是变量,也可以是常量 
- 
构造方法 有构造方法,但是不能直接实例化(可以通过多态) 那么,构造方法的作用是什么呢?用于子类访问父类数据的初始化 
- 
成员方法 可以有抽象方法:限定子类必须完成某些动作(子类要重写抽象方法) 也可以有非抽象方法:提高代码复用性 package com.szy002; /* 抽象类 */ public abstract class Animal2 { private int age=20; private final String city="北京"; public Animal2(){ //无参构造方法 } public Animal2(int age){//带参构造方法 this.age=age; } public void show(){ age=40; System.out.println(age); // city="上海";常量不可赋值 System.out.println(city); } public abstract void eat();//抽象方法 }package com.szy002; public class Cat2 extends Animal2{ @Override public void eat() {//重写父类的抽象方法 System.out.println("猫吃鱼"); } }package com.szy002; /* 测试类 */ public class AnimalDemo2 { public static void main(String[] args) { Animal2 a=new Cat2(); a.eat(); a.show(); } }
案例:猫和狗(抽象类)
需求:请采用抽象类的思想实现猫和狗的案例,并在测试类中进行测试
package com.szy003;
public abstract class Animal3 {
    private String name;
    private int age;
    public Animal3() {
    }
    public Animal3(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 abstract void eat();
}
package com.szy003;
public class Cat3 extends Animal3{
    public Cat3() {//无参构造方法
    }
    public Cat3(String name, int age) {//带参构造方法
        super(name, age);
    }
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
}
package com.szy003;
public class Dog3 extends Animal3{
    public Dog3() {//无参构造方法
    }
    public Dog3(String name, int age) {//带参构造方法
        super(name, age);
    }
    @Override
    public void eat() {
        System.out.println("狗吃肉");
    }
}
package com.szy003;
/*
测试类
 */
public class AnimalDemo3 {
    public static void main(String[] args) {
        Animal3 a=new Cat3();//采用无参构造方法
        a.setName("加菲");
        a.setAge(3);
        System.out.println(a.getName()+a.getAge());
        a=new Cat3("小花",4);//采用带参构造方法
        System.out.println(a.getName()+a.getAge());
        a=new Dog3();
        a.setName("小白");
        a.setAge(7);
        System.out.println(a.getName()+a.getAge());
        a=new Dog3("二黄",9);
        System.out.println(a.getName()+a.getAge());
    }
}
2.接口
2.1接口概述
接口就是一种公共的规范标准,只要符合规范标准,大家都可以通用
Java中的接口更多的体现在对行为的抽象
2.2接口的特点
- 
接口用关键字interface修饰 public interface 接口名{} 
- 
类实现接口用implements表示 public class 类名 implements 接口名{} 
- 
接口不能实例化 接口如何实例化呢?参照多态的方式,通过实现类对象实例化,这叫接口多态。 多态的形式:具体类多态,抽象类多态,接口类多态。 多态的前提:有继承或者实现关系;有方法重写;有父(类/接口)引用指向(子/实现)类对象 
- 
接口的实现类: 要么重写接口中的所有抽象方法,要么是抽象类。 
package com.szy004;
/*
定义了一个接口
 */
public interface Jumpping {
    public abstract void jump();//定义一个抽象方法
}
package com.szy004;
public class Cat4 implements Jumpping{//类实现接口
    @Override
    public void jump() {
        System.out.println("猫可以跳高了");
    }
}
package com.szy004;
public abstract class Dog4 implements Jumpping{
    //抽象类在实现接口时可以不重写接口的抽象方法,但是它具体的子类将来继承它的时候还是要重写接口的抽象方法
}
package com.szy004;
/*
测试类
 */
public class JumppingDemo {
    public static void main(String[] args) {
//        Jumpping j=new Jumpping();不可以实例化
        Jumpping j=new Cat4();
        j.jump();
    }
}
2.3接口的成员特点
- 
成员变量 只能是常量 默认修饰符:public static final 
- 
构造方法 接口没有构造方法,因为接口主要是对行为进行抽象的,是没有具体存在 一个类如果没有父类,默认继承自Object类 
- 
成员方法 只能是抽象方法 默认修饰符:public abstract 关于接口中的方法,JDK8和JDK9中有一些新特性,后面再讲解 
package com.szy005;
public interface Inter {
    public int num=10;
    public final int num2=20;
    public static final int num3=30;//接口中默认是public static final这种类型
//    int num3=30;与上面的等价
//    public Inter(){}报错,接口里不能有构造方法的
//    public void show();接口里面不能有非抽象方法的
    public abstract void method();
    void show();//接口里的方法默认带了public abstract
}
package com.szy005;
/*
接口实现类
 */
//public class InterImpl implements Inter{
public class InterImpl extends Object implements  Inter{//等价与上面的
   public InterImpl(){
        super();
    }
    @Override
    public void method() {//重写接口的抽象方法method()
        System.out.println("method");
    }
    @Override
    public void show() {//重写接口的抽象方法show()
        System.out.println("show");
    }
}
package com.szy005;
/*
测试类
 */
public class InterfaceDemo {
    public static void main(String[] args) {
        Inter i= new InterImpl();
//        i.num=20;报错,因为接口中的变量默认被final修饰
        System.out.println(i.num);
//        i.num2=40;报错,因为num2被final修饰了
        System.out.println(i.num2);
        System.out.println(Inter.num);//通过接口名直接访问num,说明num也是被静态修饰的
    }
}
案例:猫和狗(接口)
需求:对猫和狗进行训练,他们就可以跳高了,这里加入了跳高功能,请采用抽象类和接口来实现猫狗案例,并在测试类中进行测试。
package com.szy006;
/*
接口
 */
public interface Jumpping6 {
    public abstract void jump();
}
package com.szy006;
public abstract class Animal6 {
    private String name;
    private int age;
    public Animal6() {
    }
    public Animal6(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 abstract void eat();
}
package com.szy006;
public class Cat6 extends Animal6 implements Jumpping6{
    public Cat6() {
    }
    public Cat6(String name, int age) {
        super(name, age);
    }
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
    @Override
    public void jump() {
        System.out.println("猫可以跳高了");
    }
}
package com.szy006;
public class Dog6 extends Animal6 implements Jumpping6{
    public Dog6() {
    }
    public Dog6(String name, int age) {
        super(name, age);
    }
    @Override
    public void eat() {
        System.out.println("狗啃骨头");
    }
    @Override
    public void jump() {
        System.out.println("狗可以跳高了");
    }
}
package com.szy006;
/*
测试类
 */
public class AnimalDemo6 {
    public static void main(String[] args) {
        //创建对象,调用方法
        Jumpping6 j=new Cat6();
        j.jump();
        System.out.println("-----------");
        Animal6 a=new Cat6();
        a.setName("加菲");
        a.setAge(8);
        System.out.println(a.getName()+":"+a.getAge());
        a.eat();
        ((Cat6)a).jump();//a为Animal6类型的,不能直接调用jump方法
        System.out.println("----------");
        a=new Cat6("布偶",3);
        System.out.println(a.getName()+":"+a.getAge());
        a.eat();
        ((Cat6)a).jump();//a为Animal6类型的,不能直接调用jump方法
        System.out.println("----------");
        Cat6 c=new Cat6();
        c.setName("蓝宝石");
        c.setAge(4);
        System.out.println(c.getName()+":"+c.getAge());
        c.eat();
        c.jump();
        System.out.println("************");
        Animal6 b=new Dog6();
        b.setName("金毛");
        b.setAge(8);
        System.out.println(b.getName()+":"+b.getAge());
        b.eat();
        ((Dog6)b).jump();
        System.out.println("-------------");
        b=new Dog6("阿布",6);
        System.out.println(b.getName()+":"+b.getAge());
        b.eat();
        ((Dog6)b).jump();
        System.out.println("-------------");
        Dog6 d=new Dog6();
        d.setName("哈士奇");
        d.setAge(12);
        System.out.println(d.getName()+":"+d.getAge());
        d.eat();
        d.jump();
        System.out.println("-----------");
    }
}
2.4类和接口的关系
- 类和类的关系:继承关系,只能单继承,但是可以多层继承。
- 类和接口的关系:实现关系,可以单实现,也可以多实现,还可以继承一个类的同时实现多个接口。
- 接口和接口的关系:继承关系,可以单继承,也可以多继承。
package com.szy007;
/*
接口1
 */
public interface Inter1 {
}
package com.szy007;
/*
接口2
 */
public interface Inter2 {
}
package com.szy007;
/*
接口3
 */
public interface Inter3 extends Inter1,Inter2{//接口之间可以单继承,也可以多继承
}
package com.szy007;
/*
实现类
 */
public class InterImpl extends Object implements Inter1,Inter2,Inter3{
    //类可以继承类的同时实现多个接口
}
2.5抽象类和接口的区别
- 
成员区别 抽象类:变量,常量;有构造方法;有抽象方法;也有非抽象方法 接口:常量;抽象方法 
- 
关系区别 类与类:继承,单继承 类与接口:实现,可以单实现,也可以多实现 接口与接口:继承,单继承,多继承 
- 
设计理念区别: 抽象类:对类抽象,包括属性、行为 接口:对行为抽象,主要是行为 
案例:运动员和教练
需求:我们现在有乒乓球运动员和篮球运动员,乒乓球教练和篮球教练。为了出国交流,跟乒乓球相关的人员都需要学习英语。请用所学知识分析,这个案例中有哪些具体类,哪些抽象类,哪些接口,并用代码实现。
分析:从具体到抽象
实现:从抽象到具体
使用:使用的是具体的类的对象
package com.szy008;
/*
说英语接口
 */
public interface SpeakEnglish {
    public abstract void speakEnglish();
}
package com.szy008;
/*
抽象类-人类
 */
public abstract class Person {
    private String name;
    private int age;
    public Person() {
    }
    public Person(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 abstract void eat();//抽象的eat方法
}
package com.szy008;
/*
抽象类-教练类
 */
public abstract class  Coach extends Person {
    public Coach() {
    }
    public Coach(String name, int age) {
        super(name, age);
    }
    public abstract void teach();
}
package com.szy008;
/*
抽象类-运动员类
 */
public abstract class Player extends Person{
    public Player() {
    }
    public Player(String name, int age) {
        super(name, age);
    }
    public abstract void study();
}
package com.szy008;
//具体类-篮球教练类
public  class BasketballCoach extends Coach{
    public BasketballCoach() {
    }
    public BasketballCoach(String name, int age) {
        super(name, age);
    }
    @Override
    public void teach() {
        System.out.println("篮球教练教运动员如何投篮");
    }
    @Override
    public void eat() {
        System.out.println("篮球教练吃羊肉");
    }
}
package com.szy008;
//具体类-乒乓教练类
public class PingPangCoach extends Coach implements SpeakEnglish{
    public PingPangCoach() {
    }
    public PingPangCoach(String name, int age) {
        super(name, age);
    }
    @Override
    public void teach() {
        System.out.println("乒乓教练教运动员正反手");
    }
    @Override
    public void eat() {
        System.out.println("乒乓球教练吃烤红薯");
    }
    @Override
    public void speakEnglish() {
        System.out.println("乒乓球教练说英语");
    }
}
package com.szy008;
/*
具体类-篮球运动员类
 */
public class BasketballPlayer extends Player{
    public BasketballPlayer() {
    }
    public BasketballPlayer(String name, int age) {
        super(name, age);
    }
    @Override
    public void study() {
        System.out.println("篮球运动员学投篮");
    }
    @Override
    public void eat() {
        System.out.println("篮球运动员喝牛奶");
    }
}
package com.szy008;
/*
具体类-乒乓球运动员类
 */
public class PingPangPlayer extends Player implements SpeakEnglish{
    public PingPangPlayer() {
    }
    public PingPangPlayer(String name, int age) {
        super(name, age);
    }
    @Override
    public void study() {
        System.out.println("乒乓球运动员学习正反手");
    }
    @Override
    public void eat() {
        System.out.println("乒乓球运动员喝椰子汁");
    }
    @Override
    public void speakEnglish() {
        System.out.println("乒乓球运动员说英语");
    }
}
package com.szy008;
/*
测试类
 */
public class PersonDemo {
    public static void main(String[] args) {
        //创建对象
        PingPangPlayer p1=new PingPangPlayer();
        p1.setName("王浩");
        p1.setAge(23);
        System.out.println(p1.getName()+p1.getAge());
        p1.study();
        p1.eat();
        p1.speakEnglish();
        BasketballPlayer b1=new BasketballPlayer();
        b1.setName("章正");
        b1.setAge(33);
        System.out.println(b1.getName()+b1.getAge());
        b1.study();
        b1.eat();
    }
}
3.形参和返回值
3.1类名作为形参和返回值
- 
方法的形参是类名,其实需要的是该类的对象 
- 
方法的返回值是类名,其实返回的是该类的对象 package com.szy009; public class Cat9 { public void eat(){ System.out.println("猫吃鱼"); } }package com.szy009; public class CatOperator { public void useCat(Cat9 c){//类名作为形参 c.eat(); } public Cat9 getCat(){//类名作为返回值 Cat9 c=new Cat9(); return c; } }package com.szy009; /* 测试类 */ public class Cat9Demo { public static void main(String[] args) { //创建操作类对象,并调用方法 CatOperator c1=new CatOperator(); Cat9 c2=new Cat9(); c1.useCat(c2); Cat9 c3=c1.getCat(); c3.eat(); } }
3.2抽象类名作为形参和返回值
- 方法的形参是抽象类名,其实需要的是该抽象类的子类对象
- 方法的返回值是抽象类名,其实返回的是该抽象类的子类对象
package com.szy010;
public abstract class Animal10 {
    public abstract void eat();
}
package com.szy010;
public class Cat10 extends Animal10{
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
}
package com.szy010;
public class AnimalOperator10 {
    public void useAnimal(Animal10 a){
        a.eat();
    }
    public Animal10 getAnimal(){
        Animal10 a=new Cat10();
        return a;
    }
}
package com.szy010;
/*
测试类
 */
public class Animal10Demo {
    public static void main(String[] args) {
        //创建操作类对象,并调用方法
        AnimalOperator10 a1=new AnimalOperator10();
        Animal10 a2=new Cat10();
        a1.useAnimal(a2);
        Animal10 a3=a1.getAnimal();
        a3.eat();
    }
}
3.3接口名作为形参和返回值
- 
方法的形参是接口名,其实需要的是该接口的实现类对象 
- 
方法的返回值是接口名,其实返回的是该接口的实现类对象 package com.szy011; /*接口*/ public interface Jumpping { void jump(); }package com.szy011; /* 操作类 */ public class JumppingOpreator { public void useJumppig(Jumpping j){ j.jump(); } public Jumpping getJumpping(){ Jumpping j=new Cat11(); return j; } }package com.szy011; /* 接口的实现类 */ public class Cat11 implements Jumpping{ @Override public void jump() { System.out.println("猫猫跳高"); } }package com.szy011; /* 测试类 */ public class JumppingDemo { public static void main(String[] args) { //创建操作类对象,并调用方法 JumppingOpreator jo=new JumppingOpreator(); Jumpping j=new Cat11(); jo.useJumppig(j); Jumpping j2=jo.getJumpping(); j.jump(); } }
package com.szy011;
/*
测试类
*/
public class JumppingDemo {
public static void main(String[] args) {
//创建操作类对象,并调用方法
JumppingOpreator jo=new JumppingOpreator();
Jumpping j=new Cat11();
jo.useJumppig(j);
    Jumpping j2=jo.getJumpping();
    j.jump();
}
}
 
                    
                     
                    
                 
                    
                
 
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号