Java第二阶段---12继承---第二节 方法重写(override)
1.概念
子类中的一个成员方法与父类中的成员方法有相同的签名(方法名加上参数数量和参数类型)和返回值类型的实例方法重写了父类的方法
2.如何使用方法重写
子类重写方法的能力使类可以从行为“足够近”的父类继承,然后根据需要修改行为。重写方法与被重写的方法具有相同的名称,数量和参数类型,并且返回类型相同。重写方法还可以返回重写方法返回的类型的子类型,此子类型称为协变返回类型。
重写方法时,您可能需要使用@Override注解,该注释指示编译器您打算重写父类中的方法。如果由于某种原因,编译器检测到该方法在父类中不存在,则它将生产错误。
byte short int long float double
数字对应的类:Byte Short Integer Long Float Double => 都是Number的子类
3.案例
几何图形都有面积和周长,不同的几何图形,面积和周长的算法也不一样。矩形有长和宽,通过长和宽能够计算矩形的面积和周长;圆有半径,通过半径可以计算圆的面积和周长。请使用继承相关的知识完成程序设计。
package com.cyx.inheritance.shape;
/**
* 几何图形
*/
public class Shape {
/**
* 计算周长
* @return
*/
public Number calculatePerimeter(){
return 0;
}
/**
* 计算面积
* @return
*/
public Number calculateArea(){
return 0;
}
}
package com.cyx.inheritance.shape;
/**
* 矩形
*/
public class Rectangle extends Shape {
private int width;
private int length;
//生成构造方法
public Rectangle(int width, int length) {
this.width = width;
this.length = length;
}
public Integer calculatePerimeter(){
return (width+length) * 2;
}
public Integer calculateArea(){
return width * length;
}
}
package com.cyx.inheritance.shape;
/**
* 圆
*/
public class Circle extends Shape {
private int radius;
public Circle(int radius) {
this.radius = radius;
}
@Override
public Double calculatePerimeter(){
return 2 * Math.PI * radius;
}
@Override
public Double calculateArea(){
return Math.PI * radius * radius;
}
}
package com.cyx.inheritance.shape;
public class ShapeTest {
public static void main(String[] args) {
Shape s1 = new Rectangle(10,9);
System.out.println(s1.calculatePerimeter());
System.out.println(s1.calculateArea());
Shape s2 = new Circle(5);
System.out.println(s2.calculatePerimeter());
System.out.println(s2.calculateArea());
}
}
重写方法时访问修饰符的级别不能降低
4.super关键字
如果子类的构造方法没有明确调用父类的构造方法,java编译器会自动插入一个父类无参构造的调用,如果父类没有无参构造,你将得到一个编译时错误。Object类有一个无参构造,因此,如果Object类是该类的唯一父类,这就没有问题。
(如果一个类没有构造方法,编译器在编译的时候会自动插入一个无参构造方法)
示例一:子类和父类中都没有定义构造方法
package com.cyx.inheritance;
public class Father {
public Father(){
super();
}
String name;
public String sex;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
protected void eat(){
System.out.println("吃饭");
}
public void sleep(){
System.out.println("睡觉");
}
}
package com.cyx.inheritance;
public class Child extends Father{
//如果一个类中没有定义构造方法,那么编译器将会为该类插入一个无参构造方法
public Child(){
super();//如果子类构造方法中没有显示的调用父类的构造方法,俺么编译器会自动插入一个父类无参构造的调用
}
public void show(){
System.out.println(name);//本类中未定义name变量,但是却可以使用,说明name变量是从父类中继承过来的
System.out.println(sex);
eat();
sleep();
}
}
示例二:子类中有定义构造方法,父类中没有定义构造方法
package com.cyx.inheritance;
public class Father {
String name;
public String sex;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
protected void eat(){
System.out.println("吃饭");
}
public void sleep(){
System.out.println("睡觉");
}
}
package com.cyx.inheritance;
public class Child extends Father{
//如果一个类中没有定义构造方法,那么编译器将会为该类插入一个无参构造方法
public Child(){
super();//如果子类构造方法中没有显示的调用父类的构造方法,俺么编译器会自动插入一个父类无参构造的调用
}
public Child(String name){
super();
this.name = name;
}
public void show(){
System.out.println(name);//本类中未定义name变量,但是却可以使用,说明name变量是从父类中继承过来的
System.out.println(sex);
eat();
sleep();
}
}
示例三:子类和父类中都有定义构造方法
package com.cyx.inheritance;
public class Father {
public Father(String name,String sex){
this.name = name;
this.sex = sex;
}
String name;
public String sex;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
protected void eat(){
System.out.println("吃饭");
}
public void sleep(){
System.out.println("睡觉");
}
}
package com.cyx.inheritance;
public class Child extends Father{
//如果父类中定义了带参构造,并且没有定义无参构造,那么必须在子类的构造方法中显示的调用父类的带参构造(即自己把父类的带参写上去)
public Child(String name,String sex){
super(name,sex);
}
public void show(){
System.out.println(name);//本类中未定义name变量,但是却可以使用,说明name变量是从父类中继承过来的
System.out.println(sex);
eat();
sleep();
}
}
使用super调用父类的构造方法时,必须为这个构造方法的第一条语句
如果你的方法重写了父类的方法之一,则可以通过使用关键字super来调用父类中被重写的方法。你也可以使用super来引用隐藏字段(尽管不建议使用隐藏字段)。
package com.cyx.inheritance.p3;
public class Person {
protected String name;
protected String sex;
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package com.cyx.inheritance.p3;
public class Student extends Person{
private String name;//此时这个name 就会将父类中的name隐藏掉
public Student(String name) {
this.name = name;
}
// @Override
// public String getName() {
// return name;
// }
public void show(){
System.out.println(this.name);//访问本类中定义的name变量
System.out.println(super.name);//访问父类中定义的name变量
//如果子类中和父类中没有相同的成员变量,此时使用this和super均可以调用父类的成员变量
System.out.println(this.sex);
System.out.println(super.sex);
}
}
package com.cyx.inheritance.p3;
public class PersonTest {
public static void main(String[] args) {
Student s = new Student("张三");
s.setSex("男");
s.show();
}
}
思考:如果子类中的静态方法与父类中的静态方法具有相同的签名,是否属于方法重写?
不属于方法重写,因为静态方法称之为类方法,跟对象无关,调用时只看对象的数据类型。
package com.cyx.inheritance.p4;
public class StaticFather {
public static void show(){
System.out.println("这是父类的静态方法");
}
}
package com.cyx.inheritance.p4;
public class StaticChild extends StaticFather{
public static void show(){
System.out.println("这是子类的静态方法");
}
}
package com.cyx.inheritance.p4;
public class StaticTest {
public static void main(String[] args) {
StaticFather f = new StaticChild();//跟对象无关,只看类型
f.show();
StaticFather.show();
StaticChild.show();
}
}
5.万物皆对象
除了没有父类的object之外,每个类都有一个且只有一个直接父类(单继承)。在没有其他任何显示超类的情况下,每个类都隐式为objetc的子类。
类可以派生自另一个类,另一个类又可以派生自另一个类,依此类推,并最终派生自醉顶层的类object。据说这样的类是继承链中所有类的后代,并延伸到object。
所有类都是object的子类,因此,创建对象时都需要调用object类中的无参构造方法,而object本身就表示对象,因此创建出来的都是对象。
原文地址:https://blog.csdn.net/2301_80300263/article/details/142772009
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!