java的多态概念:
多态(英语:polymorphism),是指计算机程序运行时,相同的消息可能会送给多个不同的类别之对象,而系统可依据对象所属类别,引发对应类别的方法,而有不同的行为。简单来说,所谓多态意指相同的消息给予不同的对象会引发不同的动作称之。
多态可分为变量多态与函数多态。变量多态是指:基类型的变量(对于C++是引用或指针)可以被赋值基类型对象,也可以被赋值派生类型的对象。函数多态是指,相同的函数调用界面(函数名与实参表),传送给一个对象变量,可以有不同的行为,这视该对象变量所指向的对象类型而定。因此,变量多态是函数多态的基础。
下面举一个例子:
比如有动物(Animal)之类别(Class),而且由动物继承出类别鸡(Chicken)和类别狗(Dog),并对同一源自类别动物(父类别)之一消息有不同、的响应,如类别动物有“叫()”之动作,而类别鸡会“啼叫()”,类别狗则会“吠叫()”,则称之为多态。
概括:
上面关于多态的概念看起来有那么一点难以理解,但是我们可以把上述一大段话给归纳成为一句话就是:相同的消息可能会送给多个不同的类别之对象,而系统可依据对象所属类别,引发对应类别的方法,而有不同的行为。
代码实例:
interface perimeter_area{ //周长 public void perimeter(); //面积 public void area(); } //圆 class circle implements perimeter_area{ //定义半径 double radius; //定义构造函数 public circle(double radius){ this.radius = radius; } @Override public void perimeter() { System.out.println("圆形的周长是:"+(2*3.14*radius)); } @Override public void area() { System.out.println("圆形的面积是:"+(3.14*radius*radius)); } } //三角形 class triangle implements perimeter_area{ double a; double b; double c; public triangle(double a,double b,double c){ this.a = a; this.b = b; this.c = c; } @Override public void perimeter() { System.out.println("三角形的周长是:"+(a+b+c)); } @Override public void area() { double m = (a+b+c)/2; double n = m*(m-a)*(m-b)*(m-c); double area = Math.sqrt(n); System.out.println("三角形的面积是:"+area); } } //正方形 class square implements perimeter_area{ double a; public square(double a){ this.a =a; } @Override public void perimeter() { System.out.println("正方形的周长是:"+(a*4)); } @Override public void area() { System.out.println("正方形的面积是:"+(a*a)); } }
for循环的案例,产生随机数长度的菱形:
这里需要标注一下产生随机数的方法:
int count = r.nextInt(10) + 3;
接下来总结一下重写和重载规则
方法重写的原则:
重写方法的方法名称、参数列表必须与原方法的相同,返回类型可以相同也可以是原类型的子类型(从Java SE5开始支持)。
重写方法不能比原方法访问性差(即访问权限不允许缩小)。
重写方法不能比原方法抛出更多的异常。
被重写的方法不能是final类型,因为final修饰的方法是无法重写的。
被重写的方法不能为private,否则在其子类中只是新定义了一个方法,并没有对其进行重写。
被重写的方法不能为static。如果父类中的方法为静态的,而子类中的方法不是静态的,但是两个方法除了这一点外其他都满足重写条件,那么会发生编译错误;反之亦然。即使父类和子类中的方法都是静态的,并且满足重写条件,但是仍然不会发生重写,因为静态方法是在编译的时候把静态方法和类的引用类型进行匹配。
重写是发生在运行时的,因为编译期编译器不知道并且没办法确定该去调用哪个方法,JVM会在代码运行的时候作出决定。
方法重载的原则:
方法名称必须相同。
参数列表必须不同(个数不同、或类型不同、参数类型排列顺序不同等)。
方法的返回类型可以相同也可以不相同。
仅仅返回类型不同不足以成为方法的重载。
重载是发生在编译时的,因为编译器可以根据参数的类型来选择使用哪个方法。
重写和重载的不同:
方法重写要求参数列表必须一致,而方法重载要求参数列表必须不一致。
方法重写要求返回类型必须一致(或为其子类型),方法重载对此没有要求。
方法重写只能用于子类重写父类的方法,方法重载用于同一个类中的所有方法。
方法重写对方法的访问权限和抛出的异常有特殊的要求,而方法重载在这方面没有任何限制。
父类的一个方法只能被子类重写一次,而一个方法可以在所有的类中可以被重载多次。
重载是编译时多态,重写是运行时多态。