组团学

面向对象的三大特征-继承

阅读 (344840)

1、继承概述

1.1、什么是继承

继承是面向对象的核心特性,是面向对象的学习重点。同时继承是代码复用的重要方式,可以表示类与类之间的关系,是所有面向对象语言不可缺少的组成部分。

1.2、继承由来

1.2.1、子类与父类

当一个类的属性与行为均与现有类相似,属于现有类的一种时,这一个类可以定义为现有类的子类。

或者换成相反的角度来看,如果多个类具有相同的属性和行为,我们可以抽取出共性的内容定义父类,这时再创建相似的类时只要继承父类即可。

1.2.2、子类与父类关系

子类拥有父类的所有属性与方法,无需重新定义。并且可以直接使用非私有的父类成员。

从类与类之间的设计关系来看,子类必须属于父类的一种时,才会继承。

我们在完成一个庞大项目体系的时候,都是将共性的内容抽取出,后续构建过程是从各种父类“向外”扩散的。

2、继承定义及使用

2.1、继承定义

格式:

class 子类 extends 父类{ //父类的非私有方法与属性均继承过来 }

案例:

class Person{ private String name; public void eat(){ System.out.println(“吃饭”); } //get/set方法 }

子类继承父类的定义:

class ChinesePerson extends Person{}

2.2、继承使用

继承关系的产生通常是为了定义出功能更为具体、更为强大的子类。所以,定义子类后,一般创建子类对象使用。子类可以直接使用父类非私有的成员变量与成员方法(注:如果成员变量没有使用private修饰,则子类也可直接访问。)

class PersonDemo{ public static void main(String[] args) { ChinesePerson  c = new ChinesePerson(); c.setName("张大力"); String name = c.getName(); System.out.println(name);//打印结果为张大力 c.eat();  //打印结果吃饭 }

3、继承关系

image20191216153257678.png

动物类可以有姓名、年龄的成员变量,可以有吃饭、睡觉的方法。

所有猫科与犬科均有动物的成员变量与成员方法,且猫科与犬科均属于动物,所以猫科与犬科均可以继承动物类。

猫科可以在动物的基础上再添加抓老鼠的方法

犬科可以在动物的基础上再添加看门的方法

犬科与猫科仍可以继续出现子类,如波斯猫、巴厘猫、沙皮狗、斑点狗等,而其子类仍可以再出现该品种的特性。

案例:

/*  * Animal的类  * 属性  * name * age  * 行为  * 吃  * 睡 */ public class Animal { //成员变量 private String name; private int age; //吃 public void eat(){ System.out.println("吃"); } //睡 public void sleep(){ System.out.println("睡"); } //-----------get/set------------------- public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
/*  *定义一个猫类  * 属性  *  name    *  age  *  kind  * 行为  *  吃  *  睡  *  抓老鼠  */ public class Cat extends Animal { private String kind; @Override public void eat(){ System.out.println("猫吃鱼"); } //猫特有的功能  抓老鼠 public void catchMouse(){ System.out.println("抓耗子"); } public String getKind() { return kind; } public void setKind(String kind) { this.kind = kind; } }
/*  *定义一个狗类  * 属性  *  name    *  age  *  kind  * 行为  *  吃  *  睡  *  看门  */ public class Dog extends Animal { private String kind; @Override public void eat() { System.out.println("狗吃肉"); } //狗特有功能  看门 public void lookDoor() { System.out.println("看门"); } public String getKind() { return kind; } public void setKind(String kind) { this.kind = kind; } }
/*  * 自定义类型 家  * 地址  * 行为  * 在家吃饭  */ public class Home { private String address; //动物在家吃饭 //在所有使用父类类型的地方均可以传入其子类对象。 public void eatAtHome(Animal a) { //调用Animal的eat方法 a.eat(); } //狗在在家吃饭 public void eatAtHome(Dog dog) { System.out.println("狗在家吃了"); //调用狗的eat方法 dog.eat(); } //猫在家吃饭 public void eatAtHome(Cat cat) { System.out.println("猫在家吃了"); //调用猫的eat方法 cat.eat(); } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }
/**  * 测试家类 */ public class Test { public static void main(String[] args) { //  创建Home对象 Home home = new Home(); Animal a = new Animal(); home.eatAtHome(a); //在所有使用父类类型的地方均可以传入其子类对象。 Dog d = new Dog(); home.eatAtHome(d); Cat c = new Cat(); home.eatAtHome(c); } }

运行结果:

image20200112110827835.png

4、继承注意事项

4.1、Java只支持单继承,不支持多继承。即只能有一个父类。

//单继承 class A extends B{} class B extends C{} //多继承,错误 class A extends B{} class A extends C{}

4.2、父类可以继续有父类。

class A extends B{} class B extends C{}

4.3、所有类均有父类,只有Object类没有父类。

class A{} //相当于 class A extends Object{}//所有类都继承了Object类,继承Object类可以省略

4.4、在所有使用父类类型的地方均可以传入其子类对象。

class B{} class A extends B{} //测试类 class C{ public void c(B b){} public static void main(String args[]){ new C().c(new A()); } }

5、方法重写

5.1、什么是方法重写

当子类继承父类后,拥有了父类的成员并可以直接调用父类非私有方法。如果子类认为父类提供的方法不够强大,子类可以按照子类自身的逻辑重新定义继承过来的父类方法,这个重新定义一个方法的过程叫做方法重写。(注:在学习完多态和抽象类后我们会对方法重写有更深的理解)

5.2、方法重写格式

子类中定义与父类一样的方法便将父类的方法重写了。此时,当创建子类对象,调用方法时,会调用子类重写后的方法。

案例1:

父类

public class Person{ private String name; public void eat(){ System.out.println("吃饭"); } //get/set public String getName() { return name; } public void setName(String name) { this.name = name; } }

子类

public class ChinesePerson extends Person{ @Override //@Override是用于强制规定当前定义的方法一定为重写的方法 public void eat() { System.out.println("按照中国的习惯,使用筷子吃"); } }

子类使用

public class PersonDemo{ public static void main(String[] args) { ChinesePerson c = new ChinesePerson(); c.setName("张大力"); //父类继承方法直接调用 String name = c.getName(); //父类继承方法直接调用 System.out.println(name); //打印结果为张大力 c.eat(); //方法重写后调用的为重写后的方法 //打印结果:按照中国的习惯,使用筷子吃 } }

运行结果:

image20200112112515466.png

案例2:

public class Person{ private String name; String address;//增加了一个地址成员,可初始化 public void eat(){ System.out.println("吃饭"); } //get/set public String getName() { return name; } public void setName(String name) { this.name = name; } }
/*  * 定义类型  学生类  *  * 姓名  年龄  *  * 继承  *   概念1    *     *   方法重写  *    子类继承父类后,可以直接使用父类的非私有成员,但是如果觉得父类的成员方法不够强大,子类可以按照自身的逻辑  *    将继承过来的父类方法,进行重写(方法重写,方法复写,方法覆盖)  *     *   可以使用@Override来验证你的方法是不是重写方法。  */ public class Student extends Person{ private String number; public void method(){ System.out.println(address); System.out.println(getName()); } //重写父类eat方法 @Override public void eat(){ System.out.println("学生吃学生套餐"); } public String getNumber() { return number; } public void setNumber(String number) { this.number = number; } } 
/*  * 测试继承后的Studnet  */ public class StudentDemo { public static void main(String[] args) { //创建Studnet对象 Student s = new Student(); s.setName("柳柳"); s.setNumber("0900112"); s.eat(); String name = s.getName(); System.out.println(name); System.out.println(s.getNumber()); System.out.println("-----------------"); //子类调用自己特有的方法 s.method(); } }

运行结果:

image20200112113133686.png

5.3、方法重写规则

子类重写方法时,在声明前加@Override可检测该方法是否为重写的方法

访问权限相同或子类方法访问权限更大(访问权限顺序public>默认)

class Fu{ void show(){}   public void method(){} } class Zi extends Fu{ public void show(){}  //编译运行没问题   void method(){}      //编译错误 }

方法名称必须相同

参数列表必须相同

返回值为基本类型时必须相同

返回值为引用类型时相同或子类小(了解)

案例:

/*  * 方法重写的注意事项  *  子类重写方法时,在声明前加@Override可检测该方法是否为重写的方法  *  访问权限相同或子类方法访问权限更大(访问权限顺序public>默认)  *  方法名称必须相同  *  参数列表必须相同  *  返回值为基本类型时必须相同  *  返回值为引用类型时相同或子类小(了解)  */ public class Fu {  public void method(){ System.out.println(" 父类方法"); }     public int sum(){  return 0;  }      public Person get(){  return null;  } } 
public class Zi extends Fu//访问权限相同或子类方法访问权限更大(访问权限顺序public>默认) @Override  public void method(){ System.out.println("子类方法"); }  //返回值为基本类型时必须相同 @Override public int sum(){ return 100; } //返回值为引用类型时相同或子类小(了解) @Override public Student get(){ return null; } }
需要 登录 才可以提问哦