Heim  >  Artikel  >  Java  >  So verwenden Sie abstrakte Java-Klassen und -Schnittstellen

So verwenden Sie abstrakte Java-Klassen und -Schnittstellen

WBOY
WBOYnach vorne
2023-05-16 09:58:12894Durchsuche

Was ist eine abstrakte Klasse?

Was ist eine abstrakte Klasse? Wie der Name schon sagt, sind abstrakte Klassen sehr abstrakt. Das heißt, wenn wir nicht genügend Informationen haben, um diese Klasse zu beschreiben, müssen wir sie nicht beschreiben.

Verwenden Sie Code als Beispiel:

class Shape {
    public void draw() {
        System.out.println("我要画图形!!");
    }
}
class circle extends Shape {
    @Override
    public void draw() {
        System.out.println("我要画圆形!!!");
    }
}
class rect extends Shape {
    @Override
    public void draw() {
        System.out.println("我要画矩形!!!");
    }
}
public class TestDemo3 {
    public static void drawShape(Shape shape) {
        shape.draw();
    }
    public static void main(String[] args) {
        drawShape(new circle());
        drawShape(new rect());
    }
}

Verwenden Sie einfach diesen kleinen Fall, um den Polymorphismus zu überprüfen. Wir erstellen eine Shape-Elternklasse und erstellen dann zwei Unterklassen, nämlich die Rect-Klasse und die Circle-Klasse, und verwenden dann diese beiden Klassen die gleiche Methode, aber die resultierenden Formen sind unterschiedlich, aber

Wir können feststellen, dass ich nur diese beiden Unterklassen verwende, bei denen es sich um Kreise und Rechtecke handelt. Ich rufe dies nicht auf Methode, warum? ? ? Da diese übergeordnete Klasse keine Grafiken zeichnen kann, ist die Implementierung der Zeichenmethode dieser übergeordneten Klasse nur nutzlos, um diese Methode über die übergeordnete Klasse neu zu schreiben konkrete Umsetzungen.

Richtig, dies führt uns in die heutige Themen-Abstraktklasse ein

Die Zeichenmethode der obigen übergeordneten Klasse ist aufgrund ihrer spezifischen Implementierung nutzlos, sodass wir sie nicht schreiben müssen. Dies entspricht auch der Definition von eine abstrakte Klasse Wenn es nicht genügend Informationen gibt, um sie zu beschreiben, nennen wir sie eine abstrakte Klasse.

Abstrakte Klassensyntax

Die Zeichenmethode der obigen übergeordneten Klasse hat keine spezifische Implementierung, daher können wir sie als abstrakte Methode bezeichnen. Verwenden Sie Abstract, um

public abstract void draw();

So verwenden Sie abstrakte Java-Klassen und -Schnittstellen

zu ändern, aber warum wird ein Fehler gemeldet? ?

Der Grund dafür ist, dass die durch Abstract geänderte Methode als abstrakte Methode bezeichnet wird. Wenn eine Klasse eine abstrakte Methode enthält, muss die Klasse eine abstrakte Klasse sein, sodass die Klasse auch durch Abstract geändert werden muss.

So verwenden Sie abstrakte Java-Klassen und -Schnittstellen

Aber im Gegenteil, gibt es definitiv eine abstrakte Methode in einer abstrakten Klasse? ? ?

So verwenden Sie abstrakte Java-Klassen und -Schnittstellen

Der Compiler meldet keinen Fehler, daher lautet die Antwort nicht unbedingt: Abstrakte Klassen können abstrakte Methoden haben oder nicht.

Können abstrakte Klassen instanziiert werden? ? ?

So verwenden Sie abstrakte Java-Klassen und -Schnittstellen

Abstrakte Klassen können also nicht instanziiert werden.

Können abstrakte Klassen Mitgliedsvariablen, Methoden und Konstruktoren wie gewöhnliche Klassen definieren? ? ?

So verwenden Sie abstrakte Java-Klassen und -Schnittstellen

Der Unterschied zwischen abstrakten Klassen und gewöhnlichen Klassen besteht darin, dass abstrakte Klassen nicht instanziiert werden können und andere Definitionen von Mitgliedsvariablen, Mitgliedsmethoden, Konstruktoren usw. gleich sind.

Da abstrakte Klassen nicht instanziiert werden können, welchen Sinn hat ihre Existenz? ? ?

Das Denken von Lao Tie ist sinnvoll. Tatsächlich besteht die größte Bedeutung abstrakter Klassen in der Vererbung, da abstrakte Klassen keine Objekte instanziieren können und sich nur auf Unterklassen verlassen können, um die Methoden der übergeordneten Klasse (dh abstrakte Klassen) neu zu schreiben. um Geschäftsanforderungen zu erfüllen.

Wie erbe ich eine abstrakte Klasse? ? ? Auf welche Punkte ist zu achten? ? ?

So verwenden Sie abstrakte Java-Klassen und -Schnittstellen

Warum geht eine Vererbung so schief? ? Der Grund dafür ist, dass, wenn eine Unterklasse eine abstrakte Klasse erbt, die Unterklasse alle Methoden der übergeordneten Klasse überschreiben muss oder die Unterklasse mit abstrakt geändert werden muss (die abstrakte Klasse wird von der abstrakten Klasse geerbt oder die Unterklasse überschreibt alle Methoden der abstrakte Klasse (Elternklasse)).

So verwenden Sie abstrakte Java-Klassen und -Schnittstellen

Das ist es.

So verwenden Sie abstrakte Java-Klassen und -Schnittstellen

Beachten Sie hier auch, dass, wenn wir die Methode der übergeordneten Klasse nicht überschreiben, sondern abstrakt verwenden, um sie zu ändern, die Unterklasse dieses Mal zur übergeordneten Klasse wird, wenn Sie diese Unterklasse erben, und die nächsten Unterklassen dies noch tun müssen Überschreiben Sie weiterhin die Methoden dieser übergeordneten Klasse und die Methoden der übergeordneten Klasse dieser übergeordneten Klasse.

Können abstrakte Methoden durch statische und endgültige Methoden geändert werden? ? ?

So verwenden Sie abstrakte Java-Klassen und -Schnittstellen

Abstrakte Methoden können nicht durch statische und endgültige Methoden geändert werden, da die Unterklasse die Methode der übergeordneten Klasse überschreiben muss und das Zugriffsänderungsqualifikationsmerkmal weggelassen werden kann. Der Standardwert ist öffentlich.

Zusammenfassung der abstrakten Klassen:

  • Wir bezeichnen Klassen, die ein Objekt nicht klar genug beschreiben können, als abstrakte Klassen.

  • Durch Zusammenfassung geänderte Methoden werden als abstrakte Methoden bezeichnet, und durch Zusammenfassung geänderte Klassen werden als abstrakte Klassen bezeichnet.

  • Abstrakte Methoden müssen in abstrakten Klassen enthalten sein, dh solange abstrakte Methoden vorhanden sind, der Klassenname muss auch verwenden abstract Zum Ändern kann es im Gegensatz dazu keine abstrakte Methode in der abstrakten Klasse oder eine abstrakte Methode geben.

  • 抽象类不能实例化,除了不能实例化之外其他与普通类一样可以定义成员变量,成员方法,构造方法等。同时构造方法和类方法(被static修饰的方法)不能被abstract来修饰

  • 抽象方法的访问修饰限定符不能是private,如果省略默认是public,同时抽象方法不能被final修饰。

  • 子类继承抽象类的时候,子类必须重写抽象类的所有方法并且要有方法的具体实现,如果重写那子类还是抽象类,必须用abstract来修饰。

  • 抽象类中的方法没有具体实现,要通过子类重写在子类中实现。

  • 一个类只能继承一个抽象类

接口

说到接口我们会想到什么呢???我一开始想到的就是充电接口插排等等,比如充电接口,只要符合那个插口的标准,我们都可以使用那个接口来进行充电。这就是把标准进行统一起来,然后大家就可以根据不同的标准来使用不同的接口,比如苹果手机与安卓手机的手机接口就是不一样的,他们就是两种不同的标准,安卓手机用安卓的接口,苹果用苹果的接口这就将标准统一起来。

而在Java中也是一样的,我们把这个标准或者可以说是一种公共的规范叫做接口,只要符合这一接口的标准我们就可以使用它。

听着这抽象的概念你可能现在还是不太明白这到底是什么,我在来拿代码举个例子:

class Animal {
    public String name;
    public int age;
    public void eat() {
        System.out.println(this.name+"吃饭***!");
    }
}

这里我定义了一个动物类,这个动物有名字,年龄,还有吃饭的行为。

class Animal {
    public String name;
    public int age;
    public void eat() {
        System.out.println(this.name+"吃饭***!");
    }
    public void swim() {
        System.out.println("我要游泳~~~~");
    }
}
class Fish extends Animal {
}

接着我又定义了一个鱼类(子类)继承这个动物类(父类),我想让这个鱼有这个游泳的行为,但是这就会有一个问题,在父类定义了一个swim方法,接着我还要定义很多类,难道所有的类都要有这个游泳的行为么???答案是不可以的。所以我们就不能把这个swim方法定义在父类里面,那我们就可以把这个方法定义在子类(鱼类)里面,这样就符合了,但是如果我还要定义1000个动物都会游泳难道都要在自己类中写这个游泳的方法么??这样做显然是不可行的。那我们该怎么做呢??

我们可以就提供一个公共的接口,这也是一种标准,只要符合这一标准都可以使用这个接口或者可以说可以实现这一功能。

看了上面的引例我们应该接口是干什么的了,接下来我们来学一下接口的语法。

怎么定义接口

定义接口要使用interface关键字:

//创建一个接口
//创建接口要是用interface关键字  接口的命名最好是形容词其他的也可以
interface IFlying{
    //这就是一个flying接口
}

接口中的成员变量:

So verwenden Sie abstrakte Java-Klassen und -Schnittstellen

这样会报错,接口中的成员变量都是常量,所以必须初始化,接口中的成员变量会被隐式指定为public static final 修饰的。

interface IFlying{
    //接口中的成员变量默认都是被public static final修饰的常量
    //这里的成员变量不可改变
   public static final int a =10;
}

接口中的成员方法:

So verwenden Sie abstrakte Java-Klassen und -Schnittstellen

interface IFlying{
    //接口中的成员方法都是抽象方法,默认是public abstract 
    //其中public abstract 可以被省略
    //接口中的成员方法不能有具体的实现
    public abstract void eat();
    //一般就写成:
    //void eat();
    default void sleep(){
        //接口中的方法想要具体实现,要加上default修饰
    }
    //接口中可以有静态方法的具体实现
    public static void method() {
        System.out.println("我是静态的方法!!");
    }
}

接口能否实例化???

So verwenden Sie abstrakte Java-Klassen und -Schnittstellen

接口是不能被实例化的。

怎么使用接口???

实现的接口如下:

interface IFlying{
    void eat();
}
interface IRunning{
    void run();
}
interface ISwimming{
    void swim();
}
interface IClimbing{
    void climb();
}
//创建一个Ant类 
//利用implements关键字来实现接口
//一个类可以实现多个接口,接口之间利用逗号连接
//实现了接口必须要在接口中重写接口中的方法
//重写方法快捷键:鼠标移动到implements关键字上然后 alt+enter
class Ant implements IClimbing,IRunning{
    public String name;
    @Override
    public void run() {
        System.out.println(this.name+"要跑步");
    }
    @Override
    public void climb() {
        System.out.println(this.name+"爬山");
    }
}
  • 接口的使用时利用implements关键字与类连接,类与接口之间使用implements连接的。

  • 一个类可以实现多个接口,多个接口之间利用逗号连接。

  • class Ant implements IClimbing,IRunning.的意思是类Ant可以实现两个功能,既可以爬又可以跑。

  • 类实现接口时,必须要重写接口中的方法。如果不重写该类还是抽象类,要用abstract来修饰。

接口能否有静态方法和代码块呢???

So verwenden Sie abstrakte Java-Klassen und -Schnittstellen

接口中是不能有静态代码块和构造方法的。 

接口间的继承

我们这里总结一下类与接口之间的联系

  • 类与类之间是继承关系利用extends来连接   代表子类继承了父类

  • 类与接口之间是利用implements来连接, 代表类能实现某个功能

  • 接口与接口之间也可以进行联系,利用extends 接口A和接口B  interface A enxtends B 代表接口A拓展了接口B的功能。

这里来讲一下接口与接口之间的继承

我们利用extends关键字将两个接口连接起来,这样就实现了接口之间的继承。

例如:

interface IRunning extends IFlying{
    //类IRunning拓展了IFlying的功能
    void run();
    //接口与接口之间继承后IRunning拓展了IFlying功能
    //有了IRunning的功能的类也要重写IFlying这个方法
}
  • 类IRunning拓展了IFlying的功能

  • 接口与接口之间继承后IRunning拓展了IFlying功能

  • 有了IRunning的功能的类也要重写IFlying这个方法

几个重要的接口

接口comparable

我们这里举一个例子:

比如我们要进行给一个学生进行排序,我们之前学过Arrays的sort方法,好我们来尝试一下这个方法对学生进排序。

class Student{
    public String name;
    public int age;
    public double score;
    public Student(String name, int age, double score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", score=" + score +
                '}';
    }
}
public class TestDemo {
    public static void main(String[] args) {
        Student[] student = new Student[4];
        student[0] = new Student("张三",18,88);
        student[1] = new Student("李四",98,98);
        student[2] = new Student("王二麻子",8,18);
        student[3] = new Student("赵老八",58,38);
        System.out.println(Arrays.toString(student));
        Arrays.sort(student);
        System.out.println(Arrays.toString(student));
    }
}

So verwenden Sie abstrakte Java-Klassen und -Schnittstellen

从这里发现Arrays.sort方法是比较具体的数字大小的,而我们这里比较学生这个对象并没有指定,我们究竟依靠什么来比较这个学生对象,目前这个学生有名字,分数,年龄,我们到底依靠什么比较是根据我们的需求来定,那我们要具体的比较学生对象的某一个学生怎么比较呢·???看报错信息也就是这个异常,我们需要提供这个comparable这个接口然后重写这个comparable方法。

怎样提供接口????

So verwenden Sie abstrakte Java-Klassen und -Schnittstellen

 我们根据类要实现一个接口是利用关键字implements来连接的。

So verwenden Sie abstrakte Java-Klassen und -Schnittstellen

 然后使用comparable这个接口,尖括号里面写上你要排序的类。

好这样我们就实现了这个接口,当然看前面那个红线就知道会有报错,这也就是当我们实现一个接口我们必须重写这个接口中的方法,然后Alt+enter重写这个接口中的方法。

So verwenden Sie abstrakte Java-Klassen und -Schnittstellen

好,我们就重写了这样的一个方法,比如我们要比较年龄按照升序排列:

So verwenden Sie abstrakte Java-Klassen und -Schnittstellen 

然后调用Arrays.sort方法就可以进行排序了。

So verwenden Sie abstrakte Java-Klassen und -Schnittstellen

 同样我们还可以根据名字排序:

So verwenden Sie abstrakte Java-Klassen und -Schnittstellen

由于,名字是String类型也就是引用类型所以我们要调用compareTo方法来进行比较。

同样的我们还可以根据分数来排序这个学生对象。

So verwenden Sie abstrakte Java-Klassen und -Schnittstellen

 comparator接口-比较器

我们刚才使用comparable这个接口会有一个缺陷,就比如当我们已经实现按照年龄排序好了,但是有个人突然把他改成了名字比较,如果是未来做项目开发的时候,那就会给程序猿造成很大的困扰,就怕有一天别人修改了那段代码,所以我们就有了这个comparator这个比较器,我们还是把他封装起来,不用在去学生这个类中去修改。

对学生年龄排序:

class AgeComparator implements Comparator<Student>{
    @Override
    public int compare(Student o1, Student o2) {
        return o1.age - o2.age;
    }
}

对学生分数排序:

class ScoreComparator implements Comparator<Student>{
    @Override
    public int compare(Student o1, Student o2) {
        return (int)(o1.score - o2.score);
    }
}
对学生名字排序:
class NameComparator implements Comparator<Student>{
    @Override
    public int compare(Student o1, Student o2) {
        return o1.name.compareTo(o2.name);
    }
}

我们还是利用Arrays.sort方法里面再加一个比较器的这个参数就可以比较了。

 public static void main(String[] args) {
        Student[] student = new Student[4];
        student[0] = new Student("张三",18,88);
        student[1] = new Student("李四",98,98);
        student[2] = new Student("王二麻子",8,18);
        student[3] = new Student("赵老八",58,38);
        System.out.println(Arrays.toString(student));
        AgeComparator ageComparator = new AgeComparator();
        Arrays.sort(student,ageComparator);
        System.out.println(Arrays.toString(student));
    }

这样我们将根据什么排序,实例化对应的对象,通过对象调用重写comparator的方法就可以进行比较,不需要担心类中被修改。

cloneable接口深入理解深拷贝与浅拷贝

我们之前学过数组中的克隆方法,就是把一个数组中的内容全部拷贝到另外一个数组中去。

今天我们学的cloneable接口可以将一个对象的属性拷贝到另外一个对象里面去。

怎么使用cloneable接口

我们创建一个人这个类,人这个类中有两个属性,一个是分数,一个是smartphone这个对象(引用类型)。

class SmartPhone{
    public int money = 9999;
}
class Person{
    public int score = 96;
    SmartPhone smartPhone = new SmartPhone();
}
public class TestDemo {
    public static void main(String[] args){
        Person person1 = new Person();
    }
}

我们现在要将这个person这个类实现cloneable接口,利用implements连接,同样的我们要重写这个cloneable这个接口中的方法。

So verwenden Sie abstrakte Java-Klassen und -Schnittstellen

这里我们要注意·重写cloneable这个方法,它的返回类型是object,object是Java中所有类的父类。

好,完成了接口的操作,我们接下来完成克隆的工作,我们怎么使用clone这个方法来进行克隆呢???

浅拷贝:
//浅拷贝
class SmartPhone{
    public int money = 9999;
}
class Person implements  Cloneable{
    public int score = 96;
    SmartPhone smartPhone = new SmartPhone();
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
    @Override
    public String toString() {
        return "Person{" +
                "score=" + score +
                ", smartPhone=" + smartPhone +
                &#39;}&#39;;
    }
}
public class TestDemo {
    public static void main(String[] args) throws CloneNotSupportedException {
        Person person1 = new Person();
        Person person2 = (Person)person1.clone();
        System.out.println(person1.smartPhone.money);
        System.out.println(person2.smartPhone.money);
        person1.smartPhone.money=9;
        System.out.println("===============拷贝之后=================");
        System.out.println(person1.smartPhone.money);
        System.out.println(person2.smartPhone.money);
    }
}

So verwenden Sie abstrakte Java-Klassen und -Schnittstellen

 原因是什么呢??画一下图理解一下

So verwenden Sie abstrakte Java-Klassen und -Schnittstellen

 这就是浅拷贝,对基本数据类型进行值传递,对引用数据类型进行引用传递般的拷贝,此

为浅拷贝。只要将money值进行修改两个对象的money的值都改变,没有彻底的拷贝。

深拷贝
//深拷贝
class SmartPhone implements  Cloneable{
    public int money = 9999;
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
    @Override
    public String toString() {
        return "SmartPhone{" +
                "money=" + money +
                &#39;}&#39;;
    }
}
class Person implements  Cloneable{
    public int score = 96;
    SmartPhone smartPhone = new SmartPhone();
    @Override
    protected Object clone() throws CloneNotSupportedException {
        Person tmp = (Person)super.clone();
        tmp.smartPhone= (SmartPhone) this.smartPhone.clone();
        return tmp;
    }
    @Override
    public String toString() {
        return "Person{" +
                "score=" + score +
                ", smartPhone=" + smartPhone +
                &#39;}&#39;;
    }
}
public class TestDemo {
    public static void main(String[] args) throws CloneNotSupportedException {
        Person person1 = new Person();
        Person person2 = (Person)person1.clone();
        System.out.println(person1.smartPhone.money);
        System.out.println(person2.smartPhone.money);
        person1.smartPhone.money=9;
        System.out.println("===============拷贝之后=================");
        System.out.println(person1.smartPhone.money);
        System.out.println(person2.smartPhone.money);
    }
}

So verwenden Sie abstrakte Java-Klassen und -Schnittstellen

 此时为深拷贝,进行了彻底的拷贝。对基本数据类型进行值传递,对引用数据类型,创建一个新的对象,并复制其内容,此为深拷贝。

So verwenden Sie abstrakte Java-Klassen und -Schnittstellen

Das obige ist der detaillierte Inhalt vonSo verwenden Sie abstrakte Java-Klassen und -Schnittstellen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:yisu.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen