继承

8继承

8.1什么是继承?

继承是从已有的类中派生出新的类,新的类能够吸收已有的类的属性和方法,并能派生出新的属性和方法。(换种说话,从已有的类中提取共有的属性和方法,把它作为父类,已有的类都继承这个类。)

8.2为什么要使用继承?

使用继承可以优化设计

Dog

name  ,health,love

strain

Print()

 

Penguin

name  ,health,love

Sex

Print()

 

Pet 

name  ,health,love

Print()

 

8.3如何实现继承?

1.定义父类

2.子类 extends  父类

 

extends  关键字

[访问修饰符] class pet{

共有的属性 和方法

}

 

[访问修饰符] class Dog extends Pet{

子类特有的属性和方法

}

 

java 只支持单根继承,每个子类只能有一个直接父类,一个父类可以被多个子类继承。

8.4子类访问父类成员

1)使用super关键字,super代表父类对象 ;

2)在子类构造方法中调用且必须是第一句。

3)不可以访问父类中定义为private的属性和方法。

访问父类构造方法

super()  表示调用父类的无参构造

super(name)  表示调用父类的带参构造  super(属性1,属性2,属性3….)

访问父类属性

super.name

访问父类方法

super.print()   super.方法名  调用父类的方法

 

调用规则:

子类:没有通过this显示的调用自己的构造方法,也没有super(属性名)调用父类的带参构造方法,那么默认调用父类的无参构造方法。

子类:子类通过super(属性名)调用父类的带参构造方法,那么执行父类的带参构造,而不会执行无参构造

子类:子类构造方法通过this显示调用自身的其他构造方法时,在相应构造方法中应用以上两条规则

示例:

父类Pet

/**

 * 1.将共有的属性,和方法 抽取到父类中

 * 2.通过 extends 关键字 让子类继承父类  建立子父类之间的联系

 * 构造的调用规则:

 * super() 表示调用父类的无参构造 super(属性1,属性2,属性3...) 表示调用父类的带参构造

 * 子类中没有通过this(属性名)this()调用自身的其他构造,也没有通过super(属性名)显式的调用父类的带参构造,默认调用父类的无参构造。

 * 子类通过super(属性名)调用父类的带参构造方法,那么执行父类的带参构造,而不会执行无参构造

 * 子类:子类构造方法通过this显示调用自身的其他构造方法时,在相应构造方法中应用以上两条规则

 * super.方法名()  表示调用父类的方法

* @author Administrator

*/

public class Pet {

private String name; //名字

private int health;//健康值

private int love; //亲密度

/**

 * 父类里无参构造

 */

public Pet() {

System.out.println("调用了父类Pet中的无参构造Pet()");

}

/**

 * 父类里带2个参数 name,health的构造

 * @param name

 * @param health

 */

public Pet(String name,int health){

super(); //表示Object基类中的无参构造 ,super()写不写都一样,不写默认也会调用

this.name = name;

this.health = health;

System.out.println("调用了父类Pet中带2个参数的构造Pet(name,health)");

}

/**

 * 父类Pet的构造中,只能出现super()表示调用基类Object的无参构造 ,this(),this(属性名) 表示调用自身的其他构造 ,不可能出现super(属性名)

 * @param name

 * @param health

 * @param love

 */

public Pet(String name, int health, int love) {

this(name,health);

this.love = love;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public int getHealth() {

return health;

}

public void setHealth(int health) {

this.health = health;

}

public int getLove() {

return love;

}

public void setLove(int love) {

this.love = love;

}

public void print(){

System.out.print("宠物的自白:\n我叫"+this.getName()+",我的健康值是:"+this.getHealth()+",和主人的亲密度为:"+this.getLove());

}

}

子类Dog

/**

 * 1如何写子父类之间带参构造

 * 2.如何调用父类的方法 super.方法名

 * @author Administrator

 *

 */

public class Dog extends Pet {

private String strain; //品种 狗狗特有的属性

/**

 * 无参构造

 */

public Dog() {

super();

System.out.println("调用了子类Dog()中的无参构造");

}

/**

 * 2个参数namestrain的构造

 * @param name

 * @param strain

 */

public Dog(String name,String strain){

super(); //表示显示的调用父类里的无参构造,写不写都一样,默认都会去调用父类的无参构造

//super.方法名 调用父类Petset方法给name属性赋值  this.setName(name);

super.setName(name);

this.strain = strain;

System.out.println("调用了子类Dog(name,strain)中带2个参数的构造");

}

/**

 * 3个参数 name,health,strain的构造

 * @param name

 * @param health

 * @param strain

 */

public Dog(String name,int health,String strain){

super(name,health); //super(属性名)调用父类里带2个参数的构造

this.strain = strain;

System.out.println("调用了子类Dog(name,health,strain)中带3个参数的构造");

}

/**

 * 子类Dog中带4个参数的构造

 * @param name

 * @param health

 * @param love

 * @param strain

 */

public Dog(String name,int health,int love,String strain){

this(name,health,strain); //调用自身的带3个参数的构造,给name,health,strain3个属性赋值

super.setLove(love);

System.out.println("调用了子类Dog(name,health,love,strain)中带4个参数的构造");

}

public String getStrain() {

return strain;

}

public void setStrain(String strain) {

this.strain = strain;

}

public void print(){

//先去调用父类的print()显示前3个属性的信息

super.print();

System.out.println(",我是一只"+this.getStrain());

}

}

子类Penguin:

public class Penguin extends Pet {

private String sex; //性别 企鹅特有的属性

public Penguin() {

}

public Penguin(String name,int health,int love,String sex) {

/*super.setName(name);

super.setHealth(health);

super.setLove(love);*/

super(name,health,love);

this.sex = sex;

}

public String getSex() {

return sex;

}

public void setSex(String sex) {

this.sex = sex;

}

public void print(){

super.print();

System.out.println(",我的性别是:"+this.getSex());

}

}

8.5子类继承父类什么?

只能继承public protected 修饰的,不管在不在同一包里

继承默认(default)修饰的,只能在同一个包里

构造方法不能继承。只能调用 ,通过super调用。

8.6何时用继承?

is-a 关系的设计使用继承 (猫是一种哺乳动物,藏獒是一种狗)

8.7 重写Override

子类根据需求对父类继承的方法进行重新编写,

重写时,可以用super.方法的方式来保留父类的方法

构造方法不能被重写

方法重写的规则:

方法名相同

参数列表相同

返回值类型相同或者是其子类

访问权限不能严于父类

(如果父类方法用protected修饰 ,子类可以用protected,public ,如果父类用default修饰的,子类可以用defaultprotected,public

父类的静态方法不能被子类覆盖为非静态方法,父类的非静态方法不能被子类覆盖为静态方法。

子类可以定义与父类同名的静态方法,以便在子类中隐藏父类的静态方法。

父类的私有方法不能被子类覆盖

不能抛出比父类方法更多的异常,运行时异常除外。

面试题: 重写和重载的区别

方法重写:父子类, 方法同名,同参,返回值相同或是其子类,访问权限不能严于父类的方法权限

方法重载:同一个类 方法同名,参数列表不同(个数,类型,顺序),和返回值,访问权限无关。

示例:

import java.io.FileNotFoundException;

import java.text.ParseException;

public class Base {

public void ceshi1(){

System.out.println("hello");

}

void ceshi2(){

System.out.println("测试2");

}

protected void ceshi2(String name,String sex){

}

public int ceshi3(int a){

return a;

}

public Base getBase(){

return new Base();

}

/**

 * 父类的静态方法

 */

public static void ceshi4(){

}

/**

 * 父类的非静态方法(普通方法)

 */

public void ceshi5(){

}

public static void ceshi6(){

System.out.println("父类Base中的静态方法ceshi6()");

}

private void ceshi7(int a){

System.out.println(10);

}

/**

 * 该方法抛出2个可查的异常

 * @throws FileNotFoundException

 * @throws ParseException

 */

public void ceshi8() throws FileNotFoundException,ParseException{

}

/**

 * 该方法抛出2个运行时异常

 * @throws ArithmeticException

 * @throws NullPointerException

 */

public void ceshi9() throws ArithmeticException,NullPointerException{

}

}

import java.io.FileNotFoundException;

import java.text.ParseException;

public class Sub extends Base {

public void ceshi1(){

System.out.println("world");

}

/**

 * 编译错误 ,访问权限(访问修饰符级别>=父类的方法的访问级别) 不能严于父类,

 */

/*private void ceshi2(){

System.out.println("子类里的测试2");

}*/

protected/*public*/ void ceshi2(){

}

/**

 * 重写,参数列表相同

 */

protected void ceshi2(String name,String sex){

}

/**

 * 重写,返回值类型和父类相同

 */

public int ceshi3(int b){

return b;

}

/**

 * 重写,返回值类型是其子类

 */

public Sub getBase(){

return new Sub();

}

/**

 * 编译错误,不是重写,父类的静态方法不能被子类覆盖为非静态方法

 */

/*public  void ceshi4(){

}*/

/**

 * 编译错误,不是重写 父类的非静态方法不能被子类覆盖为静态方法

 */

/*public static void ceshi5(){

}*/

/**

 *不是重写, 只是子类定义了父类同名的静态方法

 */

public static void ceshi6(){

System.out.println("子类Sub中的静态方法ceshi6()");

}

/**

 * 不是重写,此处的ceshi7(int a)和父类Base中的私有方法ceshi7(int a),没有任何关系,就是方法同名

 * 父类Base中的ceshi7(int a) 该方法的作用域只在类Base中有效,超过该类,任何地方都访问不到

 * @param a

 */

public void ceshi7(int a){

System.out.println(12);

}

/**

 * 不能抛出比父类方法更多的异常

 */

/*public void ceshi8() throws FileNotFoundException,ParseException,ClassNotFoundException{

}*/

/**

 * 虽然抛出了比父类更多的异常,但是这些异常是运行时异常,所以不会编译出错,仍旧是重写

 */

public void ceshi9() throws ArithmeticException,NullPointerException,ClassCastException,ArrayStoreException{

}

}

8.8继承下构造方法的执行过程

例题1

package com.njwb.inherit2;

class Person{

private String name;

 

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public Person() {

//super(); //调用Object基类的无参构造

System.out.println("execute Person()");

}

 

public Person(String name) {

super();

this.name = name;

System.out.println("execute Person(name)");

}

}

/**

 * 学生类 继承Person人类

 * @author Administrator

 *

 */

class Student extends Person{

private String school; //学校

 

public String getSchool() {

return school;

}

 

public void setSchool(String school) {

this.school = school;

}

public Student() {

System.out.println("execute Student()");

}

 

public Student(String name,String school) {

super(name);

this.school = school;

System.out.println("execute School(name,school)");

}

}

/**

 * 研究生类 继承学生类

 * @author Administrator

 *

 */

class PostGraduate extends Student{

private String guide; //导师

 

public String getGuide() {

return guide;

}

 

public void setGuide(String guide) {

this.guide = guide;

}

public PostGraduate() {

System.out.println("execute PostGraduate()");

}

 

public PostGraduate(String name,String school,String guide) {

super(name,school);

this.guide = guide;

System.out.println("executePostGraduate(name,school,guide) ");

}

}

 

@SuppressWarnings("unused")

public class TestStudent {

public static void main(String[] args) {

PostGraduate post = new PostGraduate();

System.out.println("---------------------\n");

PostGraduate post2 = new PostGraduate("张三","北京大学","王教授");

}

}

示例2

父类的实例成员 --à父类的构造---à子类的实例成员----à子类的构造

class Father{

int num =getNum() ; //实例成员   getNum()虽然是静态方法,但是赋值给num变量,num是实例成员

public static int getNum(){

System.out.println("1父类Father中的getNum()");

return 10;

}

public Father() {

System.out.println("2父类Father的无参构造");

}

}

 

class Son extends Father{

int num2 = getNum2(); //实例成员

public static int getNum2(){

System.out.println("3子类Son中的getNum2()");

return 20;

}

public Son() {

System.out.println("4子类Son无参构造");

}

}

public class Test2 {

public static void main(String[] args) {

Son son = new Son();

}

}

注意:加载顺序:启动类(java虚拟机启动时,被标明为启动类的类)static block 最先加载(父类静态成员,静态代码块----子类静态成员,静态代码块---父类实例成员,代码块-----父类构造函数------子类实例成员,代码块---子类构造函数)

8.9 final修饰属性、方法和类

final 修饰成员变量,则成为实例常量

final修饰类,类不能被继承

final修饰成员方法,则该方法不能被子类重写。

8.10常量类

/**

 * 将项目中能够用到的常量都存放在一个类里,这个类叫做常量类

 * @author Administrator

 *

 */

public class Constant {

public final String GENDER="";

public final double PI=3.14;

public final int MAX_COUNT=100;

}

8.11作业

见《封装和继承上机实践》

网吧管理系统

User用户类,包含用户名、密码等相关属性

UserManager用户管理类,有一个存放用户的数组,数组的每一个元素是一个User

方法包括添加用户、删除用户、编辑用户、查询所有用户

UserManagerSystem测试类,包含main方法,调用UserManager用户管理类的增删改查。

   

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值