重载与重写
在Java编程语言中,有两个概念非常相近,很容易混淆。它们就是重写与重载。
这里先在类继承的话题上,继续来说说重写,也叫覆盖。
没有继承,就不可能有重写。这是子类对父类的一种特殊操作。这里先提一下,重载主要发生在同一个类中的操作,也可以发生在父类与子类之间。
当一个子类继承了一个父类时,它也同时继承了父类的属性和方法。我们可以直接使用父类的属性和方法,或者,如果父类的方法不能满足子类的需求,则可以在子类中对父类的方法进行“改造”,这个“改造”的过程在Java中称为“覆盖(override)”。
比如,假设我们在Person 类中定义了一个方法用于显示姓名,如下:
public String showName(){
return name;
}
那么,在子类Teacher中,就会继承这个父类的showName()方法,此时,即使Teacher类中没有定义showName()方法,也可以在它的实例(instance)中使用这个方法。
比如,我们实例化了一个Teacher的实例,这是就可以直接调用从Teacher的父类Person中继承的这个showName()方法。如下:
Teacher teacher = new Teacher();
teacher.showName();
但是,我们在Teacher类中,我们或许需要在姓名后面加上“老师”,比如,“张三”就显示为“张三老师”,那么,这个时候就需要在子类“Teacher”中对从父类中继承的showName()方法进行“改造”,也就是在子类Teacher中覆盖父类Person的方法showName():
public class Teacher extends Person{
… …
public String showName(){
return name+”老师”;
}
}
在子类Teacher中,覆盖了父类的showName方法,在覆盖的过程中,需要提供和父类中的被覆盖方法相同的方法名称、输入参数(此处为空)以及返回类型。
另外,在子类对父类的方法进行覆盖的过程中,不能使用比父类中的被覆盖方法更严格的访问权限。
比如,父类Person中的方法showName()的修饰符是public,那么,在子类Teacher中的覆盖方法showName()就不能用protected、默认(Default)或者private等来限制。
从前面的讨论可以看出,类的继承主要可以从两方面来看:
对父类的扩充。如,在子类中加入新的属性、新的方法。
对父类的改造。比如,对方法的覆盖。
首先定义一个父类:Person,它有三个属性,分别由各自的存取方法来存取。
public class Person {
private String name;
private int age;
private String sex;
public String showName() {
return name;
}
public void setName(String theName) {
name = theName;
}
public int getAge() {
return age;
}
public void setAge(int theAge) {
age = theAge;
}
public String getSex() {
return sex;
}
public void setSex(String theSex) {
sex = theSex;
}
}
在这边,我们将它的属性的访问控制定义为Default,是因为在子类中我们需要访问这些属性。
接着,我们定义一个类“Teacher”,它继承“Person”类。
public class Teacher extends Person {
// 扩充父类属性
private String department;
// 扩充父类方法
public void setDepartment(String theDept) {
department = theDept;
}
public String getDepartment() {
return department;
}
// 方法覆盖
public String showName() {
return name + "老师";
}
// 测试
public static void main(String[] args) {
Teacher t = new Teacher();
t.setName("Alex");
System.out.println(t.showName());
}
}
在这个子类中,继承了父类,新增了一个“部门”的属性:department,并新增了相应的存取方法。改写(覆盖)了父类中的showName()方法,在姓名后面加上“老师”后返回。
因为在同一个包中的子类中用到了父类的属性name,所以,父类Person中的name属性不能定义为private的。最后定义了一个main()方法用于测试。
执行这个程序,在控制台上将会输出如下信息:
Alex老师
在程序中加入一个main()方法用于测试一个类是不错的主意,无论这个类是否是一个Java应用程序(Java Application)。
你可以通过类的main()方法测试这个类的各个方法是否与你的设计相一致。
1 重载
在Java程序中,如果同一个类(或者父类子类之间)中如果有两个相同的方法(方法名相同、返回值相同、参数列表相同)是不行的,因为这样编译器无法将方法调用和特定的方法联系起来。但是,在一个类中,如果有多个方法具有相同的名称,而有不同的参数,这种情况是允许的,我们就称这种行为为方法的重载(overload)。
我们经常使用println来向控制台输出各种类型的数据,这些println方法就是实现了方法的重载。
在进行方法的重载时,方法的参数列表必须不同(参数个数或者参数数据类型,或者两者皆不同)。而方法的返回值可以相同,也可以不同。
我们来看一个例子。还是以上面的“Person”类,我们需要取得“Person”对象的“name(姓名)”属性,可能会有两种情况:一种是直接得到对象的“name”属性,还有一种情况是在获取的对象属性“name”的方法上输入一个参数,将这个参数当作头衔和“name”结合起来,比如:输入的头衔是“先生”,则通过方法返回的是:“XXX先生”。
我们可以为这两个需求定义两个方法,但是,为了显示这两个方法的相似点,我们更倾向于使用方法重载来完成:
public class Person{
… …
public String getName() {
return name;
}
public String getName(String title) {
return name+title;
}
… …
}
这样,如果只需要得到“Person”对象的“name”属性,调用不带参数的getName()方法就可以了;如果需要得到“Person”对象的“name”属性并且需要指明它的头衔,则可以调用带一个参数的getName()方法。
在进行方法的重载时,有四条基本原则需要遵守:
方法名相同;
参数列表必须不同;
返回值可以不同;
可以相互调用。
注意:方法的返回值不是方法的签名(signature)的一部分,所以,进行方法的重载的时候,不能将返回值类型的不同当成两个方法的区别。也就是说,在同一个类中,不能有这样的两个方法,它们的方法名相同、参数相同,只是方法的返回值类型不同。
构造器重载
在前面我们说过,构造器在某种程度上可以看成是一个特殊的方法:它没有返回值,它的方法名称必需和类的名称一致。因此,构造器也常常被称为“构造方法”。
作为Java类的组成成分之一,构造器也可以进行重载,下例中的类Person就定义了4个重载的构造器以满足不同的需要。
public class Person {
private String name;
private int age;
private String sex;
public Person() {
System.out.println("构造器Person()被调用");
name = "";
}
public Person(String theName) {
System.out.println("构造器Person(String theName)被调用");
name = theName;
}
public Person(String theName, int theAge) {
System.out.println("构造器Person(String theName,int theAge)被调用");
name = theName;
age = theAge;
}
public Person(String theName, int theAge, String theSex) {
System.out.println("构造器Person(String theName,"
+ "int theAge,String theSex)被调用");
name = theName;
age = theAge;
sex = theSex;
}
// 其他代码
// …. …
}
在这个类中,定义了四个构造器,这四个构造器中,各自的参数个数都不一样。在创建对象的时候,编译器会根据参数类型和参数个数来确定到底调用哪一个构造器。
我们来看下面这个创建“Person”对象的例子:
public class NewPerson {
public static void main(String[] args) {
Person person = new Person("Tom", 18, "male");
}
}
编译并运行上面这个程序,它将会向控制台打印出如下信息:
构造器Person(String theName,int theAge,String theSex)被调用
这说明,它的带三个参数的构造器被调用来创建Person对象了。
1)方法重载(Overload)。表示两个或多个方法名字相同,但方法参数不同。方法参数不同有两层含义:1)参数个数不同。2)参数类型不同。 注意:方法的返回值对重载没有任何影响。
普通的方法在重载的情况下,可以互相调用。
2)构造方法重载:只需看参数即可。如果想在一个构造方法中调用另外一个构造方法,那么可以使用this()的方式调用,this()括号中的参数表示目标构造方法的参数。this()必须要作为构造方法的第一条语句,换句话说,this()之前不能有任何可执行的代码。
13. 方法重写(Override):又叫做覆写,子类与父类的方法返回类型一样、方法名称一样,参数一样,这样我们说
子类与父类的方法构成了重写关系。
14. 方法重写与方法重载之间的关系:重载发生在同一个类内部的两个或多个方法。重写发生在父类与子类之间。重载是一种平行关系,几个方法参数不同。重写是一种层次关系。
15. 当两个方法形成重写关系时,可以在子类方法中通过super.run()形式调用父类的run()方法,其中super.run()
不必放在第一行语句,因此此时父类对象已经构造完毕,先调用父类的run()方法还是先调用子类的run()方法是根据
程序的逻辑决定的。
Java中虚方法调用
我们前面已经知道了,在多态的情况下,声明为父类类型的引用变量只能访问父类中定义过的方法,但如果此变量实际引用的是子类的对象,而子类中又进行了方法覆盖时,实际调用的是子类中覆盖后的方法,这种机制称为虚方法调用。
在使用多态的情况下,有可能出现编译时类型和运行时的类型不一致的问题,如上面的例子中:
public class CalClass{
.. …
public int calPersonBirthYear(Person p) {
// 根据参数p的年龄来计算出生年代
}
}
在编译的时候,方法calPersonBirthYear 的参数类型是Person的,而在运行的时候,可能就是Student 或Teacher或Person或其他的Person子类类型了。
相关推荐
在编程语言中,方法重载(Overloading)和方法重写(Overriding)是两个非常重要的概念,它们都是实现多态性(Polymorphism)的关键机制。本文将深入探讨这两个概念,以及它们在实际编程中的应用。 ### 方法重载...
在C#编程语言中,重写、重载和多态是面向对象...重写允许子类定制继承自基类的方法,重载让我们可以创建多个同名但参数不同的方法,而多态则让我们可以通过父类引用调用子类的特定方法,实现更高效、更灵活的代码设计。
重载与覆写/重写的区别 区别 重载 覆写 1 单词 OverLoading Override 2 概念 方法名称相同,参数的类型或个数不同 方法名称相同,参数的类型或个数相 同,返回值类型相同 3 范围 发生在一个类之中...
方法的重载是同一个类中多态性的一种表现。 方法重载须遵循如下两条规则 (1)方法名相同。 (2)参数列表不同。 注意:方法的返回值类型不能用来区分重载的方法。这是因为当调用一个方法时,返回值...
JAVA中的方法重写与方法重载区别 JAVA 中的方法重写和方法重载是两个重要的概念,在面向对象程序设计语言中尤为重要。方法重写和方法重载都是多态性的体现,但它们之间有着本质的区别。 方法重写(Override)是指...
### Java 方法的艺术:重载与重写的深度解析 在 Java 编程语言中,方法的重载(Overloading)和重写(Overriding)是面向对象编程的重要概念。这两种技术使得方法能够在不同的上下文中表现出不同的行为,从而增强了...
重写发生在父类和子类之间,当子类继承父类时,如果子类定义了一个与父类中已存在的方法同名、同参数列表的方法,那么子类中的这个方法就是对父类方法的重写。重写的主要目的是为了在子类中改变或扩展父类的功能。在...
在Java编程语言中,方法的重载(Overloading)与重写(Overriding)是两个非常重要的概念。它们虽然只有一字之差,但其实质却大相径庭。理解这两者的不同对于深入掌握Java语言至关重要。 ### 一、重载(Overloading...
### C++中重载与重写函数的区别及虚函数详解 #### 一、虚函数概述 **1.1 虚函数定义与作用** 在C++中,虚函数是一种特殊的成员函数,它允许子类覆盖父类的行为。虚函数的核心在于实现多态性,即在运行时动态决定...
重写的方法必须与父类的方法同名,同返回值,同形参个数和类型。重写的目的是为了提供更加具体的实现。 例如,在上面的例子中,`Triangle` 类中的 `getSides()` 方法是对 `Shape` 类中的 `getSides()` 方法的重写。...
Java 中重载与重写的区别 Java 中的重载(Overloading)和重写(Overriding)是两个不同的概念,它们都是 Java 语言中实现多态性的手段。 方法重载(Overloading) 方法重载是让类以统一的方式处理不同类型数据的...
Java 中重载和重写总结 Java 中的重载(Overloading)和重写(Overriding)是两个非常...方法重载是让类以统一的方式处理不同类型数据的一种手段,而方法重写是父类与子类之间的多态性,对父类的函数进行重新定义。
我根据我的理解来谈谈Java中重写方法与重载方法的区别。 重写 Java 中重写又叫覆盖,主要是指继承(extends)父类或者实现(implements)接口时将父类或者接口中已经存在的方法进行重新定义。重写的方法在父类...
在编程语言中,方法的重载(Overloading)和重写(Overriding)是两种不同的多态性表现,它们在类的继承体系中扮演着重要角色。本文将深入探讨这两种概念,以及它们在实际编程中的应用和规则。 首先,我们来看方法...
重写的方法必须与被重写的方法有完全相同的名称、返回类型和参数列表。重写的方法在子类中可以更改其行为,但不能更改其签名,也不能降低其访问权限。例如,父类有一个打印消息的方法,子类可以重写这个方法,使其...
### 重载、重写、覆盖与多态的深刻剖析 在面向对象编程语言中,如Java、C#等,重载(Overloading)、重写(Overriding)、覆盖(也称为重写)以及多态(Polymorphism)是几个非常重要的概念。它们之间既有关联又有...
- **增强代码的可维护性**:当需要增加与现有方法类似的新功能时,可以通过重载来实现,而不需要为新功能创建全新的方法名。 ### 重构(Refactoring) 重构是指在不改变程序外部行为的前提下,对内部结构进行修改,...
重写(Overriding)是指子类可以提供与父类相同签名的方法,但提供不同的实现。重写只发生在继承关系中,子类方法必须声明为`@Override`(在Java中),以确保该方法确实覆盖了父类的相应方法。在运行时,如果对象是...
Java编程语言中,方法的两种重要特性是方法重载(Overloading)和方法重写(Overriding)。这两种机制都是为了实现多态性,但它们在实际应用中有着明显的区别。 **方法重载(Overloading)**: 方法重载发生在同一...