04、抽象类与接口

 内容多,第二次复习时写的


一、抽象类

1、本质:

当一个类不能描述一个具体对象时我们把它叫做抽象类

2、与普通类的区别:

它跟普通类一样可以定义成员方法和变量,但是不能实例化,它可以和普通类一样实现多态、向上转型、动态绑定以及拥有构造方法等等

(它的主要作用就是用来继承的)


这里举个实现的例子:

public abstract class Shape1 {
    public abstract void draw();
}
public class Cycle1 extends Shape1{
    public void draw(){
        System.out.println("打印一个圆形");
    }
}
public class Rect1 extends Shape1{
    public void draw(){
        System.out.println("打印一个矩形");
    }
}
public class java0712 {
    public static void func(Shape1 shape1){ //这里实际上就是向上转型
        shape1.draw();
    }
    public static void main(String[] args) {
        func(new Cycle1());
        func(new Rect1());
    }
}

我们可以注意到,子类如果继承了抽象类,一定要重写抽象类的抽象方法,在重写时子类修饰访问权限要大于等于父类的访问权限否则会报错


还有一个要注意的小例子:

public abstract class Shape1 {
    public abstract void draw();
}
 abstract class A extends Shape1{
     abstract void text();
}
 class B extends A{
    public void draw(){

    }
    public void text(){

    }
}

这里就是说如果是一个抽象类(A)继承了一个抽象类(Shape),那就不需要重写抽象方法了,但是当另一个不是抽象类的类继承了A,那就不仅要重写A的,而且也要重写Shape的抽象方法


小结:

1、回想之前的dog和cat都继承的animal就可以定义成一个抽象类,因为它没有具体的作用,并且不能准确指定一个对象

2、private、static、final修饰方法时不能被重写


二、接口

1、定义:

任何类型只要实现了接口定义的成员,就可以被当作接口来使用,从而实现多态和代码复用等功能

2、特点:

接口中的成员变量和成员方法前面默认加了这个(如下)

public interface IShape {
//   public static final int a = 10;
   int a = 10;
//  public abstract void draw();
   void draw();
}

这样就可以让代码变得简洁了

3、性质:

接口中的方法不能有具体的实现,并且也不能进行实例化

一个类可以通过关键字implement来实现多个接口

public class Cycle2 implements IShape{
    public void draw(){
        System.out.println("打印一个圆形");
    }
    public void find(){
        System.out.println("寻找一个圆形");
    }
}
public class java0713 {
    public static void func(IShape iShape){
        iShape.draw();
        if(iShape instanceof Cycle2){
            Cycle2 cycle2 = (Cycle2) iShape;//向下转型,此时就能调用Cycle2中的方法了
            cycle2.find();
        }
    }

    public static void main(String[] args) {
        func(new Cycle2());
    }
}

那接口跟抽象类的区别是什么?

答:接口不能写构造方法,并且成员方法和成员变量类型是默认的

了解完接口得到的拓展:

1、我们可以利用一个类可以实现多个接口(用逗号隔开)的性质来间接的实现"多继承"

2、我们可以通过接口来忘记类型,直接满足接口性质就使用。


4、接口间的多继承

本质就是把多个接口合并成一个接口

interface IRunning {
 void run();
 }
 interface ISwimming {
 void swim();
 }
 // 两栖的动物,青蛙

 interface IAmphibious extends IRunning, ISwimming {
 }
 class Frog implements IAmphibious {
 ...
 }

实现这个接口的类要把他们的方法都重写了


5、两种常见的比较接口

① Comparable接口

public class Student implements Comparable{
    public String name;
    public int age;

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

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public int compareTo(Student o) {
        return this.age - o.age;
    }   //重写接口中的方法,这里属于是写死了,格式是固定的
    
    }
public class java0716{
    public static void main(String[] args) {
        Student student1 = new Student("张三",20);
        Student student2 = new Student("李四", 19);


        int a = student1.compareTo(student2); //student1调用,传入student2
        if (a > 0){
            System.out.println("student1 > student2");
        }
    }

}

这里就是通过重写现成的接口方法来实现比较的

② Coparator接口

import java.util.Comparator;

public class Student implements Comparator {
    public String name;
    public int age;

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

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public int compare(Student student1,Student student2) {
        return student1.name.compareTo(student2.name);
    }   //String中正好有compareTo,避免了字符串直接相减报错
    
    }
public class java0716{
    public static void main(String[] args) {
        Student student1 = new Student("bit",20);
        Student student2 = new Student("hello", 19);


        int a = student1.compare(student1,student2);
        if (a > 0){
            System.out.println("student1 > student2");
        }else {
            System.out.println("student1 <= student2");
        }
    }

}

这里点开String类型后发现中有compareTo方法


6、内部类

定义:

在java中,可以将一个类定义在另一个类或方法的内部,前者叫做内部类,后者叫做外部类

①静态内部类

class outclass{   //外部类
    
    public int a1 = 1;
    private int a2 = 2;
    public static int a3 = 3;
    
    public static class innerclass{ //内部类
        public int a4 = 4;
        private int a5 = 5;
        public static int a6 = 6;

        
        outclass y = new outclass();
        public void test(){
            System.out.println("内部类方法");
            
        }
    }
    
}

public class java0719 {
    public static void main(String[] args) {
       outclass.innerclass x = new outclass.innerclass();
       x.test();
    }
}

这里我们发现静态内部类调用自身成员需要实例化内部类对象,这里需要用到外部类 + ‘.’ 的形式

class outclass{   //外部类

    public int a1 = 1;
    private int a2 = 2;
    public static int a3 = 3;

    public static class innerclass{ //内部类
        public int a4 = 4;
        private int a5 = 5;
        public static int a6 = 6;


        outclass y = new outclass(); //静态内部类中不能直接访问外部非静态成员变量
        public void test(){
            System.out.println("内部类方法");
           System.out.println(y.a1);
           System.out.println(y.a2);
           System.out.println(a3);
           System.out.println(a4);
           System.out.println(a5);
           System.out.println(a6);
        }
    }

}

public class java0719 {
    public static void main(String[] args) {
       outclass.innerclass x = new outclass.innerclass();
       x.test();
    }
}

通过这几段代码我们又发现,静态内部类中不能直接访问外部非静态成员变量,需要对外部类进行实例化

②实例内部类

实例内部类获取对象时依赖外部类的引用

class outclass{   //外部类

    public int a1 = 1;
    private int a2 = 2;
    public static int a3 = 3;

    public  class innerclass{   //实例内部类
       
        public int a1 = 8;
        public int a4 = 4;
        private int a5 = 5;
        public static int a6 = 6;
        
        
        outclass y = new outclass();
        public void test(){
            System.out.println("内部类方法");
           System.out.println(y.a1);
           System.out.println(a2);
           System.out.println(a3);
           System.out.println(a4);
           System.out.println(a5);
           System.out.println(a6);
        }
    }

}

public class java0719 {
    public static void main(String[] args) {
        outclass y = new outclass();  //注意这里!!!
       outclass.innerclass x = y.new innerclass();
       x.test();
    }
}

这里我们能发现,外部内部成员变量同名时,优先内部,调用外部的话需要前面加上外部引用

③局部内部类(不常用,就先带过了)

④匿名内部类(简单认识下)

没有名字且只能用一次

interface Greeting {
 void greet();
 }
 public class Test  {
 // 
类体
 }; –¨ ˝ ¿˛
    public static void main(String[] args) {
        Greeting greeting = new Greeting() {
            @Override
            public void greet() {
                System.out.println("Hello!");
            }
        };
        greeting.greet();
    }
 }


你可能感兴趣的:(java,开发语言)