方法重载与抽象类3-13

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了方法重载与抽象类3-13相关的知识,希望对你有一定的参考价值。

方法重载与抽象类

方法重载

在一个类中,我们可以定义多个方法。如果有一系列方法,它们的功能都是类似的,只有参数有所不同,那么,可以把这一组方法名做成同名方法。例如,在​​Hello​​​类中,定义多个​​hello()​​方法:

class Hello 
public void hello()
System.out.println("Hello, world!");


public void hello(String name)
System.out.println("Hello, " + name + "!");


public void hello(String name, int age)
if (age < 18)
System.out.println("Hi, " + name + "!");
else
System.out.println("Hello, " + name + "!");


这种方法名相同,但各自的参数不同,称为方法重载(​​Overload​​)。

注意:方法重载的返回值类型通常都是相同的。

方法重载的目的是,功能类似的方法使用同一名字,更容易记住,因此,调用起来更简单。

举个例子,​​String​​类提供了多个重载方法​​indexOf()​​,可以查找子串:

  • ​int indexOf(int ch)​​:根据字符的Unicode码查找;
  • ​int indexOf(String str)​​:根据字符串查找;
  • ​int indexOf(int ch, int fromIndex)​​:根据字符查找,但指定起始位置;
  • ​int indexOf(String str, int fromIndex)​​根据字符串查找,但指定起始位置。

试一试:

// String.indexOf()

 Run

练习

public class Main 
public static void main(String[] args)
Person ming = new Person();
Person hong = new Person();
ming.setName("Xiao Ming");
// TODO: 给Person增加重载方法setName(String, String):
hong.setName("Xiao", "Hong");
System.out.println(ming.getName());
System.out.println(hong.getName());

 # 抽象类

由于多态的存在,每个子类都可以覆写父类的方法,例如:

class Person 
public void run() …


class Student extends Person
@Override
public void run() …


class Teacher extends Person
@Override
public void run() …

从​​Person​​类派生的​​Student​​和​​Teacher​​都可以覆写​​run()​​方法。

如果父类​​Person​​的​​run()​​方法没有实际意义,能否去掉方法的执行语句?

class Person 
public void run(); // Compile Error!

答案是不行,会导致编译错误,因为定义方法的时候,必须实现方法的语句。

能不能去掉父类的​​run()​​方法?

答案还是不行,因为去掉父类的​​run()​​方法,就失去了多态的特性。例如,​​runTwice()​​就无法编译:

public void runTwice(Person p) 
p.run(); // Person没有run()方法,会导致编译错误
p.run();

如果父类的方法本身不需要实现任何功能,仅仅是为了定义方法签名,目的是让子类去覆写它,那么,可以把父类的方法声明为抽象方法:

class Person 
public abstract void run();

把一个方法声明为​​abstract​​,表示它是一个抽象方法,本身没有实现任何方法语句。因为这个抽象方法本身是无法执行的,所以,​​Person​​类也无法被实例化。编译器会告诉我们,无法编译​​Person​​类,因为它包含抽象方法。

必须把​​Person​​类本身也声明为​​abstract​​,才能正确编译它:

abstract class Person 
public abstract void run();

抽象类

如果一个​​class​​定义了方法,但没有具体执行代码,这个方法就是抽象方法,抽象方法用​​abstract​​修饰。

因为无法执行抽象方法,因此这个类也必须申明为抽象类(abstract class)。

使用​​abstract​​修饰的类就是抽象类。我们无法实例化一个抽象类:

Person p = new Person(); // 编译错误

无法实例化的抽象类有什么用?

因为抽象类本身被设计成只能用于被继承,因此,抽象类可以强迫子类实现其定义的抽象方法,否则编译会报错。因此,抽象方法实际上相当于定义了“规范”。

例如,​​Person​​类定义了抽象方法​​run()​​,那么,在实现子类​​Student​​的时候,就必须覆写​​run()​​方法:

// abstract class

 Run

面向抽象编程

当我们定义了抽象类​​Person​​,以及具体的​​Student​​、​​Teacher​​子类的时候,我们可以通过抽象类​​Person​​类型去引用具体的子类的实例:

Person s = new Student();
Person t = new Teacher();

这种引用抽象类的好处在于,我们对其进行方法调用,并不关心​​Person​​类型变量的具体子类型:

// 不关心Person变量的具体子类型:
s.run();
t.run();

同样的代码,如果引用的是一个新的子类,我们仍然不关心具体类型:

// 同样不关心新的子类是如何实现run()方法的:
Person e = new Employee();
e.run();

这种尽量引用高层类型,避免引用实际子类型的方式,称之为面向抽象编程。

面向抽象编程的本质就是:

  • 上层代码只定义规范(例如:abstract class Person);
  • 不需要子类就可以实现业务逻辑(正常编译);
  • 具体的业务逻辑由不同的子类实现,调用者并不关心。

以上是关于方法重载与抽象类3-13的主要内容,如果未能解决你的问题,请参考以下文章

九 DIP 依赖倒置原则

0607-抽象类抽象方法接口类的重载类的自加载对象的克隆

依赖倒置原则(Dependence Inversion Principle,DIP)

设计模式的四种原则

设计原则-DIP依赖倒置原则

定义抽象类Shape,抽象方法为showArea(),求出面积并显示,定义矩形类Rectangle,正方形类Square,圆类 Circle,根据各自的属性,用showArea方法求出各自的面积,在m