在Java 中,重载(overload)和重写(override)是用来表现多态性的两种重要方式。override 也有译作“覆盖”、“覆写”。Java 中称作“覆写”比较恰当。
重载方法是指一个类中,方法名相同、参数列表不同的几个方法,调用时根据不同的参数调用不同的方法。方法重载与返回类型无关。
覆写方法是指子类有一个方法,方法名、参数列表、返回类型与父类的某个方法完全一致。调用时会调用子类的方法,而屏蔽掉父类的同名方法。需要注意的是,子类覆写的方法,其可访问性一定要强于或等同于,父类被覆写的同名方法。
覆写发生在子类和父类之间,当然也可以是子类和父类的父类之间。重载不仅仅是发生在子类和父类之间,大多数时候,发生在同一个类中。
4.5节说到:“ Ruby语言,只有重写,没有其它语言具有的严格意义上的重载。” 下面仔细分析 Ruby 为何没有重载,只有重写。
Java 的重载, 参数列表不同有三种形式。
一.参数个数不同
sum(int a)
sum(int a ,int b)
二.参数个数相同,参数类型不同
sum(int a)
sum(float a)
三.参数个数相同,参数类型相同,对应位置不同
sum(int a , float b)
sum(float a ,int b)
Ruby支持缺省参数,我们看程序 E6.1-1.rb :由于缺省参数和可变参数,参数个数不同而产生的重载,在Ruby中不再有效。Ruby语言中,定义方法时,不指定参数类型,因此第二种形式的重载也不存在。第三种形式的重载,实际是第二种形式的演化,所以,也就不存在了。综上所述,Ruby语言,没有方法的重载。
- def sum( a, b=5 )
- a+b
- end
- puts sum(3,6) # => 9
- puts sum(3) # => 8
调用sum(3,6) 与 调用sum(3) 在Java中是调用不同的方法,在Ruby中其实是在调用同一个方法。
Ruby还支持可变参数,我们看程序 E6.1-2.rb :
- # E6.1-2.rb
- def sum( *num )
- numSum = 0
- num.each { |i| numSum+=i }
- return numSum
- end
- puts sum() # => 0
- puts sum(3,6) # => 9
- puts sum(1,2,3,4,5,6,7,8,9) # => 45
方法的重写,我们在4.4节和4.5节已经看到了。Worker类与Student类继承自Person类,并且各自重写了Person类的talk方法。
这是在子类和父类之间,如果在同一个类中写两个同名方法呢?看程序 E6.1-3.rb :
- # E6.1-3.rb
- def talk (a)
- puts "This is talk version 1."
- end
- def talk (a,b=1)
- puts "This is talk version 2."
- end
- talk (2) # => This is talk version 2.
- talk (2,7) # => This is talk version 2.
总是写在后面的方法被执行。
从上面三个小程序可知:在Ruby中,我们说覆写是指重写,我们说重载也是指重写。
Java 和 C++ 是静态语言,程序代码运行中不可以再改变类的属性、方法,为了更好地表现面向对象的多态特征,所以用覆写和重载来加强程序的灵活性,在程序运行的时候,动态地选择要使用的方法, 完成后期绑定。而 Ruby 是动态语言,可以随时改变类的属性、方法,所以覆写和重载的重要性就降低了。仔细体会一下,一者是增大可选择性,一者是随时修改。
完整阅读,请看我写的 Ruby语言中文教程all in one