多态性也是面向对象方法的一个重要特性.多态性是指在在程序中出现的"重名"现象,即在一个程序中相同的名字可以表示不同的实现.
在JAVA中,多态性主要表现在如下两个方面:
(1)方法重载.通常指在同一个类中,相同的方法名对应着不同的方法实现,但是方法的参数不同.
(2)成员覆盖.通常指在不同类(父类和子类)中,允许有相同的变量名,但是数据类型不同;也允许有相同的方法名,但是对应的方法实现不同.
在重载的情况下,同一类中具有相同的名字的方法.如何选择它的方法体呢?不能使用类名来区分,通常采用不同的方法形参表,区分重载要求形参在类型,个数和顺序的不同,在定义重载方法时,应在方法的形参的类型,个数和顺序有所不同,以便在选择时能够区别开来.
在覆盖的情况下,同名的方法存在于不同的类中,在调用方法只要指明其方法所归属的类名就可以了.
例如
class Shape {
void draw() {}
void erase() {}
}
class Circle extends Shape {
void draw() {
System.out.println("Circle.draw()");
}
void erase() {
System.out.println("Circle.erase()"); }
}
class Square extends Shape {
void draw() {
System.out.println("Square.draw()");
}
void erase() {
System.out.println("Square.erase()");
}
}
class Triangle extends Shape {
void draw() {
System.out.println("Triangle.draw()");
}
void erase() {
System.out.println("Triangle.erase()");
}
}
public class Test {
public static Shape randShape() {
switch((int)(Math.random() * 3)) {
default:
case 0: return new Circle();
case 1: return new Square();
case 2: return new Triangle();
} }
public static void main(String[] args) {
Shape[] s = new Shape[9];
for(int i = 0; i < s.length; i++)
s[i] = randShape();
for(int i = 0; i < s.length; i++)
s[i].draw();
}
}
输出结果
Triangle.draw()
Circle.draw()
Triangle.draw()
Triangle.draw()
Triangle.draw()
Square.draw()
Square.draw()
Triangle.draw()
Circle.draw()
Triangle.erase()
Circle.erase()
Triangle.erase()
Triangle.erase()
Triangle.erase()
Square.erase()
Square.erase()
Triangle.erase()
Circle.erase()
Press any key to continue...
又一次执行
Triangle.draw()
Triangle.draw()
Circle.draw()
Circle.draw()
Circle.draw()
Triangle.draw()
Triangle.draw()
Square.draw()
Circle.draw()
Triangle.erase()
Triangle.erase()
Circle.erase()
Circle.erase()
Circle.erase()
Triangle.erase()
Triangle.erase()
Square.erase()
Circle.erase()
Press any key to continue...
两次执行结果不同的原因是其中的Math.random()这个类导致的,math.random()得到的数是0-1之间的随机数.
写到这里,我突然想到了方法重载,那么它和多态,覆盖有什么区别呢?到GOOGLE是搜素了一下,不少.
不过,最重要的一点区别是:通过方法重载进而实现对象的多态性.
方法重载是指功能相同的多个方法使用同一个方法名.同名的多个方法的参数要有所不同,即在参数类型,参数个数和参数顺序上要有所区别,以便作为选择某个方法的根据.通常只有功能相同的方法进行重载才有意义.
例如:计算两个数之和的重载方法定义如下:
int add(int i,int j)
{retrun i+j;}
float add(float i,float j)
{retrun i+j;}
double add(double i,double j)
{retrun i+j;}
重载方法的选择通常是在编译时进行.系统根据不同的参数类型,个数或顺序,寻找最佳匹配方法.方法类型不参与匹配.
下面是搜到的一些例子.
public class Base{
int a,b;
public Base(int x,int y){
a = x;
b = y;
}
public int add(){
return (a + b);
}
public void add(int x,int y){
int z;
z = x + y;
}
}
上面这段代码就是重载~~~他有三个特征
1:方法名必须一样 “add()“。
2:返回类型可以不一样 就象是 ”int “和”void“.
3:参数可以不一样 就是add() 和add(int x,int y)这样的。
2:返回类型可以不一样 就象是 ”int “和”void“.
3:参数可以不一样 就是add() 和add(int x,int y)这样的。
public class Base{
int x,y;
public void add(){
int z;
z = x + y;
}
}
public class Child extends Base{
int x,y;
public void add(){
int z;
z = x + y;
}
public static void main(string [] args){
Base b = new Child();
b.add();
}
}
下面这个例子就是重写,他实现了多态~~
重写的要求是,方法名必须一样,返回类型必须一样,传入的参数必须一样
在main函数中定义父类的对象,但是用子类去实例化他,这样就可以通过父类的对象调用到子类的方法。
下面还有一个例题.
public class Parent {
public int addValue( int a, int b) {
int s;s = a+b;return s;
}
}
class Child extends Parent {
}
Which methods can be added into class Child?
a int addValue( int a, int b ){// do something...}
b public void addValue (){// do something...}
c public int addValue( int a ){// do something...}
d public int addValue( int a, int b )throws MyException {//do something...}
答案为B.C
解释1:
a是覆盖,b ,c是重载
a的问题出在访问权限上,如果换成public也是可以的
d是异常的问题.
解释2:
a的访问权限小于父类,所以错误,d是异常错误,b和c中的addValue方法和父类的方法参数不同,所以是重载.
解释3:
在同一个类中方法成员的名称相同,但参数的类型和个数不同,这称为重载。
在存在继承关系的两个话,子类与父类的方法成员名称相同、参数的类型和个数相同的话,子类的方法覆盖父类的方法,这称为覆盖。