Java 教程 5:继承和多态

作者 : 慕源网 本文共3792个字,预计阅读时间需要10分钟 发布时间: 2022-04-14 共443人阅读

继承和多态:两个让任何 Java 初学程序员感到恐惧的大词。然而,他们所指的概念并不那么复杂。

Java中的继承

我们先来看看继承。继承允许您创建现有类的子类。你为什么要做这样的事?好吧,假设你有一门课叫Robot。Robot只包含所有Robot都需要的一些基本方法。例如:

public class Robot {
    public void start() {
        System.out.println("Robot started.");
    }
    
    public void work() {
        System.out.println("Robot working.");
    }
    
    public void stop() {
        System.out.println("Robot stopped.");
    }
}

正如您所看到的,Robot类仅仅定义了start()、work()和stop()方法,每个方法仅仅打印出它应该执行的操作。

我们将创建一个带有Main方法的类来运行Robot。

public class Application {


    public static void main(String[] args) {
        Robot robot = new Robot();
        
        robot.start();
        robot.work();
        robot.stop();

    }
}
运行此程序将生成以下输出:
Robot started.
Robot working.
Robot stopped.

如果我们想要创建特定类型的Robots ,这些Robots “继承”了Robots 的所有功能,但又添加了新的功能,该怎么办呢?

例如,让我们创建一个WasteDisposalRobot:

public class WasteDisposalRobot extends Robot {
    public void findWaste() {
        System.out.println("Finding waste");
    }
}
使用关键字extends,我们创建了一个WasteDisposalRobot,它可以执行Robot所执行的所有操作,并且还添加了一个findWaste()方法。

我们可以这样使用它:

WasteDisposalRobot robot = new WasteDisposalRobot();
        
robot.start();
robot.findWaste();
robot.work();
robot.stop();
Robot started.
Finding waste
Robot working.
Robot stopped.

我们在这里看到的是继承在起作用。WasteDisposalRobot是Robot类的subclass 或子类;Robot类是其基类或父类。

WasteDispoalRobot可以做Robot能做的所有事情,我们也可以向它添加新的方法(和数据)。

强烈推荐

海量程序代码,编程资源,无论你是小白还是大神研究借鉴别人优秀的源码产品学习成熟的专业技术强势助力帮你提高技巧与技能。在此处获取,给你一个全面升级的机会。只有你更值钱,才能更赚钱

如果你是初级程序员可以研究别人的代码提高技术,如果你喜欢搞网盟或者外包,可以让你快速建站,还等什么赶快关注吧,我们会持续输出相关资源

海量源码程序,学习别人的产品设计思维与技术实践

方法覆盖

如果我们已经创建了某个超类的新子类,但我们不喜欢超类中的一个或多个方法,该怎么办?我们想把它改成别的东西。我们可以简单地通过在子类中再次定义方法来做到这一点。

在下面的代码中,我们重写了Robot父类中的work()方法,以便它在WasteDisposalRobot子类中执行一些不同的操作。

public class WasteDisposalRobot extends Robot {
    public void findWaste() {
        System.out.println("Finding waste");
    }
    
    @Override
    public void work() {
        System.out.println("Disposing waste!");
    }
}
Robot started.
Finding waste
Disposing waste!
Robot stopped.

请注意位于被覆盖方法之前的@Override指令。这不是强制性的,但您应该始终使用它。它告诉Java编译器您打算覆盖父类中的方法。如果您拼错了方法名称并试图覆盖不存在的方法,编译器将通过抛出错误来警告您。

实例变量继承

您可能会想知道实例变量会发生什么情况。如果Robot超类有一些实例变量,子类是否也可以访问这些变量?这取决于在父类中定义实例变量时是使用public、private或protected访问说明符,还是根本不使用任何说明符。稍后我们将更详细地讨论这一点,但现在我们只说,只要实例变量不是私有的,它们就可以被子类访问。

我们来看一个例子。在这里,我将所有相关代码放在一个文件中,以使其更易于阅读。

class Fruit {
    String name;
    
    Fruit() {
        name = "Fruit";
    }
    
    public String getName() {
        return name;
    }
}

class Banana extends Fruit {
    Banana() {
        name = "Banana";
    }
}



public class Application {


    public static void main(String[] args) {
        Fruit fruit = new Fruit();
        Banana banana = new Banana();
        
        System.out.println(fruit.getName());
        System.out.println(banana.getName());
    }

}

两个类的构造函数都设置name实例变量。Banana类扩展了Fruit类(即继承自它);它的构造函数还可以访问它设置的name实例变量。然后,当使用getName()方法从任一个类中检索Name时,将返回并显示相应的名称。

Fruit
Banana

构造函数继承

构造函数像其他方法一样被继承,事实上,当你构造一个子对象时,它的父对象的默认构造函数会首先被自动调用。

class Fruit {
    Fruit() {
        System.out.println("Fruit constructed");
    }

}

class Banana extends Fruit {
    Banana() {
        System.out.println("Banana constructed");
    }
}

public class Application {

    public static void main(String[] args) {
        Banana banana = new Banana();
    }
}
Fruit constructed
Banana constructed

如果父类中没有默认构造函数,则必须在子类中显式定义构造函数。如果需要,可以使用super关键字调用父类中相应的构造函数。

class Fruit {
    Fruit(String name) {
        System.out.println("Fruit constructed with name: " + name);
    }

}

class Banana extends Fruit {
    Banana() {
        super("Banana");
    }
}

public class Application {

    public static void main(String[] args) {
        Banana banana = new Banana();
    }
}
Fruit constructed with name: Banana

Java中的多态性

多态:简单概念。它的字面意思是“许多形状”。但这说明不了什么。多态性意味着,基本上,一旦你有了一个子类,你就可以在使用父类对象的任何地方使用该子类的对象。Java将自动调用正确的方法。

例如,即使我们有一个父类类型的变量,我们也可以将其分配给子类,并且可以使用该变量调用子类中被覆盖的方法。

我们来看一个例子。

class Fruit {
    
    public void show() {
        System.out.println("Fruit");
    }
}

class Banana extends Fruit {
    
    @Override
    public void show() {
        System.out.println("Banana");
    }
    
    public void makeBananaTree() {
        System.out.println("Making a tree");
    }
}

public class Application {

    public static void main(String[] args) {
        Fruit banana = new Banana();
        
        banana.show();
        
        // The following WILL NOT work;
        // Variables of type Fruit know only
        // about Fruit methods.
        // banana.makeBananaTree();
    }
}
Banana

当然,您不能将banana赋给fruit变量,然后使用它来调用只属于banana而不属于fruit的方法。fruit只知道fruit的方法。特定类类型的变量只知道在该特定类及其超类中定义的方法。它不知道子类中定义的方法,即使您可以将子类类型的对象分配给变量(banana对象分配给fruit变量,如本例所示),并且被覆盖的方法将被正确调用。


慕源网 » Java 教程 5:继承和多态

常见问题FAQ

程序仅供学习研究,请勿用于非法用途,不得违反国家法律,否则后果自负,一切法律责任与本站无关。
请仔细阅读以上条款再购买,拍下即代表同意条款并遵守约定,谢谢大家支持理解!

发表评论

开通VIP 享更多特权,建议使用QQ登录