查看“Java继承的概念”的源代码
←
Java继承的概念
跳转至:
导航
,
搜索
因为以下原因,您没有权限编辑本页:
您所请求的操作仅限于该用户组的用户使用:
用户
您可以查看与复制此页面的源代码。
==继承的概念== 继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类。 继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。 ===例子一: 动物类别的属性=== [[文件:java5-100.jpg]] 兔子和羊属于食草动物类,狮子和豹属于食肉动物类。 食草动物和食肉动物又是属于动物类。 所以继承需要符合的关系是:is-a,父类更通用,子类更具体。 虽然食草动物和食肉动物都是属于动物,但是两者的属性和行为上有差别,所以子类会具有父类的一般特性也会具有自身的特性。 ===例子二: 汽车界的继承=== [[文件:ai20-4-31.png]] 什么叫做汽车的平台化 ?两个产品的有些系统,子系统或零件是一样的,特别是不可见部分;而对于可见部分则根据不同地区,针对不同市场及不同用户群进行个性化设计。这种相同的系统,子系统及零部件的组成,被称之为平台,也就是说,平台是由一些共用件组成,在一个平台上,通过针对市场的个性化设计,可形成多个产品。 平台化- 很多人常挂在嘴边,表征就是很多零部件是通用的,做的最厉害的是大众,有人说大众只有一款车:高尔夫。拉长就是帕萨特,改名就叫迈腾,减掉一个后座就是CC,再拉长就叫辉腾,拍成方的就是途安,加多三个后座就是夏朗,加高底盘就是途观,再撑大点就是途锐,拍扁就是尚酷,加个屁股就是速腾,缩短点就是POLO,掰弯搓圆就是甲壳虫这说明大众平台化做的多么成功,通用件多。 ==继承在开发中的应用== 假设开发动物类,其中动物分别为企鹅以及老鼠,要求如下: 企鹅:属性(姓名,id),方法(吃,睡,自我介绍) 老鼠:属性(姓名,id),方法(吃,睡,自我介绍) 企鹅类: <nowiki>public class Penguin { private String name; private int id; public Penguin(String myName, int myid) { name = myName; id = myid; } public void eat(){ System.out.println(name+"正在吃"); } public void sleep(){ System.out.println(name+"正在睡"); } public void introduction() { System.out.println("大家好!我是" + id + "号" + name + "."); } }</nowiki> 老鼠类: <nowiki>public class Mouse { private String name; private int id; public Mouse(String myName, int myid) { name = myName; id = myid; } public void eat(){ System.out.println(name+"正在吃"); } public void sleep(){ System.out.println(name+"正在睡"); } public void introduction() { System.out.println("大家好!我是" + id + "号" + name + "."); } }</nowiki> 仔细观察,发现企鹅类和老鼠类有很多相同的字段和方法,考虑到我们还有许多小动物需要开发,我们能不能集约一下,不要写这么多重复的代码? 这个时候,继承就派上用场了。 继承是面向对象编程中非常强大的一种机制,它首先可以复用代码。我们可以设计一个父类Animal类,让它具有企鹅、老鼠等小动物的普遍属性,然后企鹅类和老鼠类继承这个类之后,就获得了Person的所有功能,我们只需要为企鹅和老鼠类编写新增的功能,其他已有的功能可以全部复用自父类Animal。 Java使用extends关键字来实现继承: 父类Animal: <nowiki>public class Animal { private String name; private int id; public Animal(String myName, int myid) { name = myName; id = myid; } public void eat(){ System.out.println(name+"正在吃"); } public void sleep(){ System.out.println(name+"正在睡"); } public void introduction() { System.out.println("大家好!我是" + id + "号" + name + "."); } } </nowiki> 这个Animal类就可以作为一个父类,然后企鹅类和老鼠类继承这个类之后,就具有父类当中的属性和方法,子类就不会存在重复的代码,维护性也提高,代码也更加简洁,提高代码的复用性(复用性主要是可以多次使用,不用再多次写同样的代码) 继承之后的代码: 企鹅类: <nowiki>public class Penguin extends Animal { // 不要重复name和id字段/方法, // 只需要定义新增color字段/方法: String type; public Penguin(String myName, int myid) { super(myName, myid); this.type="type1"; } }</nowiki> 老鼠类: <nowiki>public class Mouse extends Animal { // 不要重复name和id字段/方法, // 只需要定义新增color字段/方法: String color; public Mouse(String myName, int myid) { super(myName, myid); this.color="white"; } }</nowiki> 可见,通过继承,Mouse只需要编写额外的功能,不再需要重复代码。 在OOP的术语中,我们把Animal称为超类(super class),父类(parent class),基类(base class),把Mouse称为子类(subclass),扩展类(extended class)。 ==继承的含义和格式== *继承就是子类继承父类的特征和行为,使得代码能够复用; *声明继承之后,子类就可以使用父类所有的变量和方法; *如果有变量和方法父类当中不存在,子类可以自己定义。 ===继承的格式=== 在 Java 中通过 extends 关键字可以申明一个类是从另外一个类继承而来的,一般形式如下: 类的继承格式 <nowiki>class 父类 { }</nowiki> <nowiki>class 子类 extends 父类 { }</nowiki> ===继承举例=== 【实例5-3】使用继承思想实现汽车类,以及公交车和卡车类。(重型汽车、洒水车、专用车等;软件公司有一个产品衍生的多款产品等) <nowiki>public class Car {//定义父类 public String bound;//汽车牌子 public int count;//汽车载人数 public void showInfo(){//显示汽车基本信息 System.out.print("车的牌子是:"+bound+";车载人数:"+count); } } public class Bus extends Car{//Car的子类Bus public String number;//子类自己属性-几路公交车 protected void showStation(String station){//子类自己方法-报站名 System.out.println("你到"+station); } } public class Truck extends Car{//Car的子类Truck public double weight;//子类自己属性-载重 public void loading(String things){//子类自己的方法-装货 System.out.println("车里装"+things); } }</nowiki> 本例中主要描述了关于汽车的继承关系。其中Bus和Truck分别代表公交车和货车(实体),它们都是一种汽车Car(概念)。因此Car作为了父类,Bus和Truck分别是由Car派生出来的子类。 *继承就是子类继承父类的特征和行为,使得代码能够复用; *声明继承之后,子类就可以使用父类所有的变量和方法; *如果有变量和方法父类当中不存在,子类可以自己定义。 '''【经 验】''' 我们可以看出父类都是概念性的类别词汇,例如:汽车、电灯、风扇。而汽车又可分为公交车、货车等;电灯又分为台灯、日光灯、彩灯等;风扇又可分为吊扇、台扇等。Java是面向对象程序设计语言,来形容实际存在的实体对象,所以编程前对程序需求分析应从对象入手,总结多个对象之间的相同点和不同点,把相同点抽象出来组成一个概念性的父类,把不同点作为子类自己独有的性质。因此通常情况父类是没有实例化的必要。 ==技术要点== *如何写一个子类? *子类如何继承父类的私有变量? *子类何时需要调用父类的构造方法? *子类和父类如何相互转化 ? ===如何写一个子类?=== ====extends关键字==== 在 Java 中,类的继承是单一继承,也就是说,一个子类只能拥有一个父类,所以 extends 只能继承一个类。 <nowiki>public class Animal { private String name; private int id; public Animal(String myName, String myid) { //初始化属性值 } public void eat() { //吃东西方法的具体实现 } public void sleep() { //睡觉方法的具体实现 } } public class Penguin extends Animal{ }</nowiki> ===如何引用父类的变量=== ====protected关键字==== 继承有个特点,就是子类无法访问父类的private字段或者private方法。例如,Student类就无法访问Person类的name和age字段: <nowiki>class Person { private String name; private int age; }</nowiki> <nowiki>class Student extends Person { public String hello() { return "Hello, " + name; // 编译错误:无法访问name字段 } } </nowiki> 这使得继承的作用被削弱了。为了让子类可以访问父类的字段,我们需要把private改为protected。用protected修饰的字段可以被子类访问: <nowiki>class Person { protected String name; protected int age; }</nowiki> <nowiki>class Student extends Person { public String hello() { return "Hello, " + name; // OK! } }</nowiki> 因此,protected关键字可以把字段和方法的访问权限控制在继承树内部,一个protected字段和方法可以被其子类,以及子类的子类所访问,后面我们还会详细讲解。 ====super 与 this 关键字==== super关键字:我们可以通过super关键字来实现对父类成员的访问,用来引用当前对象的父类。 this关键字:指向自己的引用。 实例 <nowiki>class Animal { void eat() { System.out.println("animal : eat"); } } class Dog extends Animal { void eat() { System.out.println("dog : eat"); } void eatTest() { this.eat(); // this 调用自己的方法 super.eat(); // super 调用父类方法 } } public class Test { public static void main(String[] args) { Animal a = new Animal(); a.eat(); Dog d = new Dog(); d.eatTest(); } } </nowiki> 输出结果为: <nowiki>animal : eat dog : eat animal : eat</nowiki> ===如何调用父类构造方法=== 子类不能继承父类的构造方法,但是为了使用方便,可以在自己的构造方法中调用它。 *如果父类没有无参数的构造方法,子类就必须显式地通过super关键字调用父类的构造器并配以适当的参数列表。 *如果父类有无参数的构造方法,则在子类的构造器中用super调用父类构造器不是必须的,因为如果我们这里不写,系统也会默默去调用下父类的构造方法。 我们来看一个例子: Person类: <nowiki> class Person { protected String name; protected int age; public Person(String name, int age) { this.name = name; this.age = age; } } </nowiki> Student类: <nowiki> class Student extends Person { protected int score; public Student(String name, int age, int score) { this.score = score; } }</nowiki> 测试类Main.java: <nowiki>public class Main { public static void main(String[] args) { Student s = new Student("Xiao Ming", 12, 89); } } </nowiki> 运行上面的代码,会得到一个编译错误,大意是在Student的构造方法中,无法调用Person的构造方法。 这是因为在Java中,任何class的构造方法,第一行语句必须是调用父类的构造方法。如果没有明确地调用父类的构造方法,编译器会帮我们自动加一句super();,所以,Student类的构造方法实际上是这样: <nowiki>class Student extends Person { protected int score; public Student(String name, int age, int score) { super(); // 自动调用父类的构造方法 this.score = score; } }</nowiki> 但是,Person类并没有无参数的构造方法,因此,编译失败。 解决方法是调用Person类存在的某个构造方法。例如: class Student extends Person { protected int score; public Student(String name, int age, int score) { super(name, age); // 调用父类的构造方法Person(String, int) this.score = score; } } 这样就可以正常编译了! *如果父类有无参构造器,则在子类的构造器中用super调用父类构造器不是必须的,可以调用,也可以不调用。 Person类: <nowiki> class Person { protected String name; protected int age; public Person( ){ } public Person(String name, int age) { this.name = name; this.age = age; } } </nowiki> Student类: <nowiki> class Student extends Person { protected int score; public Student(String name, int age, int score) { this.score = score; } }</nowiki> </nowiki> 因此我们得出结论:如果父类没有默认的构造方法,子类就必须显式调用super()并给出参数以便让编译器定位到父类的一个合适的构造方法。 这里还顺带引出了另一个问题:即子类不会继承任何父类的构造方法。子类默认的构造方法是编译器自动生成的,不是继承的。 ==继承的特性== *如果子类继承了父类,则子类自动具有父类的全部非私有的数据成员(数据结构)和成员方法(功能); *子类可以定义自己的数据成员和成员函数, 同时也可以修改父类的数据成员或重写父类的方法; *Java的继承是单继承,但是可以多重继承,单继承就是一个子类只能继承一个父类,多重继承就是,例如A类继承B类,B类继承C类,所以按照关系就是C类是B类的父类,B类是A类的父类,这是java继承区别于C++继承的一个特性。 *Java中却允许多层继承。例如,子类A可以有父类B,父类B同样也可以再拥有父类C。因此子类都是“相对”的; *在Java中,Object类为特殊超类或基类,所有的类都直接或间接地继承Object。 ==要点拾遗== 父类变量和方法的调用 父类构造方法的调用 子类新建自己的变量和方法 子类重写父类的方法 参考文档: http://www.runoob.com/java/java-override-overload.html 返回 [[Java程序设计]]
返回至
Java继承的概念
。
导航菜单
个人工具
登录
命名空间
页面
讨论
变种
视图
阅读
查看源代码
查看历史
更多
搜索
导航
首页
最近更改
随机页面
帮助
工具
链入页面
相关更改
特殊页面
页面信息