为什么java中需要方法重载和覆盖?
可能重复:
多态性与重写与重载
我很难知道为什么java中需要重载和覆盖的方法 ?
我已经阅读了一些关于此的文章,但却无法理解为什么它几乎需要它?
我还访问了stackoverflow中的下面的url,但我还不清楚这个主题。
Java重载和覆盖
任何实际的例子将不胜感激。
提前致谢。
来自doc
方法重载:假设您有一个类可以使用书法来绘制各种类型的数据(字符串,整数等),并且包含绘制每种数据类型的方法。 为每个方法使用新名称很麻烦 – 例如,drawString,drawInteger,drawFloat等。 在Java编程语言中,您可以对所有绘图方法使用相同的名称,但是为每个方法传递不同的参数列表。 因此,数据绘图类可能会声明四个名为draw的方法,每个方法都有一个不同的参数列表。
public class DataArtist { ... public void draw(String s) { ... } public void draw(int i) { ... } public void draw(double f) { ... } public void draw(int i, double f) { ... } }
重载方法由传递给方法的参数的数量和类型区分。 在代码示例中, draw(String s)
和draw(int i)
是不同且唯一的方法,因为它们需要不同的参数类型。
您不能声明具有相同名称和相同数量和类型的参数的多个方法,因为编译器无法区分它们。
在区分方法时编译器不考虑返回类型,因此即使它们具有不同的返回类型,也不能声明具有相同签名的两个方法。
在面向对象编程中, 方法重写是一种语言特性,它允许子类或子类提供已由其一个超类或父类提供的方法的特定实现。 子类中的实现通过提供与父类中的方法具有相同名称,相同参数或签名以及相同返回类型的方法来覆盖(替换)超类中的实现。 执行的方法版本将由用于调用它的对象确定。 如果父类的对象用于调用该方法,则将执行父类中的版本,但如果使用子类的对象来调用该方法,则将执行子类中的版本。
重写
Java Docs说:
子类中具有相同签名(名称,加上其参数的数量和类型)和返回类型作为超类中的实例方法的实例方法会覆盖超类的方法。
子类覆盖方法的能力允许类从行为“足够接近”的超类inheritance,然后根据需要修改行为。
覆盖是使用inheritance时可用的function。
当从另一个类扩展的类想要使用父类的大部分function并希望在某些情况下实现特定function时使用它。
在这种情况下,我们可以创建与父类具有相同名称和签名的方法。 这样,新方法将屏蔽父方法,并且默认情况下将被调用。
class Thought { public void message() { System.out.println("I feel like I am diagonally parked in a parallel universe."); } } public class Advice extends Thought { @Override // @Override annotation in Java 5 is optional but helpful. public void message() { System.out.println("Warning: Dates in calendar are closer than they appear."); } }
超载
Java中的重载是能够创建多个具有相同名称但具有不同参数的方法。
这样做的主要优点是代码清洁。
我们来看String.valueOf
方法。 此方法的重载版本定义为:
static String valueOf(boolean b) static String valueOf(char c) static String valueOf(char[] data) static String valueOf(char[] data, int offset, int count) static String valueOf(double d) static String valueOf(float f) static String valueOf(int i) static String valueOf(long l) static String valueOf(Object obj)
这意味着如果我们有任何类型的变量,我们可以使用String.valueOf(variable)
获得它的String表示。
如果不允许超载,我们的方法看起来像这样……
static String valueOfBoolean(boolean b) static String valueOfChar(char c) static String valueOfCharArray(char[] data) static String valueOfCharArrayWithOffset(char[] data, int offset, int count) static String valueOfDouble(double d) static String valueOfFloat(float f) static String valueOfInt(int i) static String valueOfLong(long l) static String valueOfObject(Object obj)
…比重载的解决方案更难以阅读。
答案主要围绕使用interface
和abstract class
es。
假设您有一段代码:
abstract class testAbstract { int a; int b; int c; public String testFunction() { System.out.println("Override me!"); return "default"; } public void setValuesByFormula(double a, double b) { System.out.println("No formula set!"); } }
这不是赌注的例子,但是我们可以说这是为了让用户从公式中设置a
, b
和c
。 用户想要创建一个新的实例:
class testClass extends testAbstract { }
类testClass
目前包含……什么都没有。 但它扩展了testAbstract
,因此具有函数setValuesByFormula
。 但是,当用户尝试调用此项时,系统会输出以下消息: No formula set!
此时用户必须做的是@Override
原始function。 因此,新课程变为:
class testClass extends testInterface { public void setValuesByFormula(double a, double b) { //A not really relevant formula goes here. } }
这将停止消息No formula set!
因为用户已经创建了自己的公式。 这需要几个主要原因:
- 如果函数是从超类inheritance的,那么孩子通常会想要覆盖该函数。 但是,超类可能具有其类的默认代码。 因此,如果用户希望使用他们自己的代码,则必须覆盖此function。
- 通常,超类希望使用默认代码确保某个函数将返回而不会出现错误。 还有其他默认代码有用的实例。 因此,这提供了另一种选择:如果用户不需要默认代码,他们可以覆盖它。