相关文章:

  1. 《面向对象再探究》:介绍了面向对象的基本概念
  2. 《详解Java的对象创建》:介绍了对象的创建、构造器的使用

《面向对象再探究》这篇文章中已经笼统的介绍过继承的概念了,下面就来具体介绍继承的使用等相关问题。

1. 引入例子

Animal类和Dog类例子,下文都会围绕该例展开。

public class Animal {
private String name;
private int age; public Animal(String name, int age) {
this.name = name;
this.age = age;
} public Animal() {
} public void say() {
System.out.println("我是" + name + ",今年" + age + "岁了");
} //getters and setters ...
}
public class Dog extends Animal {

    private String address;

    public Dog(String name, int age, String address) {
super(name, age);
this.address = address;
} public Dog() {
} public void say() {
System.out.println("我叫" + super.getName() + ",今年" + super.getAge() + "岁了,家住" + address + ",汪汪汪...");
} public void watchDoor() {
System.out.println("我在" + address +"看门...");
} //getters and setters ...
}

Dog类继承Animal类,Animal类有nameage属性和say()方法,Dog类增加了address属性和watchDoor()方法。

2. 概念介绍

在现实生活中有许多继承的例子,比如“子承父业”、“继承父母财产”、“继承某人意志”等,这些都是在强调一个体得到另一个体的东西,他们之间存在“继承关系”。

在Java中,继承是类和类之间的关系。在《面向对象再探究》这篇文章中举了动物Animal类和狗Dog类、猫Cat类、兔子Rabbit类的例子并写了代码,这里直接拿来用不再列出,请移步此文章。

我们可以说狗、猫、兔子是动物,但不可以说动物是狗、猫、兔子。动物普遍有眼睛、耳朵等属性,有跑、吃、叫等行为。狗显然也具有这些属性和行为,但是狗也具有一些它特有的属性和行为,比如灵敏的鼻子、看门等。

在这个例子中,Animal类是父类,Dog类、Cat类、Rabbit类是子类。子类和父类存在继承关系,可以说:子类“是”父类,该关系是继承的一个明显特征。

下面是关于继承的几个Q&A:

Q1: 什么时候需要用到继承?

A1: 个人认为可从以下两点出发:

  1. 面向对象语言是对现实世界的抽象,所谓“万物皆对象”,那么我们在实际开发中的类肯定都是与现实世界的实物相对应的,所以看实物之间的关系有没有继承关系。
  2. 当有若干类有大量重复的属性和方法,那么就可以考虑使用继承,将这些重复的属性和方法抽成父类。

Q2: 怎样使用继承?

A2: 子类使用extends关键字继承父类,也只有使用了该关键字后,才存在继承关系及“父子类”:

public class Animal {//父类
//属性和方法
}
public class Dog extends Animal {//子类继承父类
//属性和方法
}

Q3: 在具体开发中,是先编写父类,然后扩展出子类,还是先编写子类,然后抽象出父类?

A3: 个人认为不能一概而论。如果你的系统设计非常好,可以先写好父类,然后扩展子类。如果你没设计好,或者考虑不周,那么后期可能会出现许多类有重复代码,这时候可以考虑抽取父类。

Q4: 父类和子类在内容上有什么区别?

A4: 通常,我们将更通用的一些属性和方法放到父类中,比如狗、猫、兔子都具有的属性和方法会方法动物类中。子类中是更加特别的属性和方法,比如狗的看门行为、猫的抓老鼠行为。由于子类继承了父类,所以子类中只需要编写和父类的不同之处。

所以,子类往往会比父类拥有更加丰富的属性和方法。

Q5: 子类继承的父类的哪些东西?

A5: 这里先给出结论,下文再详细介绍。子类继承了父类的非私有private成员变量、方法、嵌套类,子类不继承父类的构造器,但是子类可以调用父类的构造器。

Q6: Java中可以继承多个类吗?

A6: Java中的继承是单继承,只能继承一个类。

3. 具体使用

3.1. 子类重写父类的方法

有时子类从父类继承得到的方法不一定适用,这时子类可以重写父类的方法。如Dog类重写了其父类的say()方法。

注意要和重载加以区分。

简单来说,重写涉及到的是两个类的同名方法,重载涉及到的是一个类的同名方法。关于重载介绍请移步这里

3.2. 子类新增属性和方法

前面提到:子类是对父类的扩展,子类内容比父类更加丰富。所以通常子类都会有自己的属性和方法,比如Dog类的address属性和watchDoor()方法。

3.3. 子类如何使用父类的私有成员?

子类不继承父类的私有成员,但是如果父类有能访问其私有成员变量的publicprotected的方法(比如getter方法),那么子类可以通过继承这些方法来使用父类的私有方法(Java官方教程)。

下面用上面的代码例子解释:

Animal类有私有成员变量、和公有方法say()say()直接访问本类的私有成员变量,没毛病!

public class Animal {
private String name;
private int age; public void say() {
System.out.println("我是" + name + ",今年" + age + "岁了");
}
//其他代码...
}

现在Dog类继承Anima

public class Dog extends Animal {

    private String address;

    public void say() {//name和age报红
System.out.println("我叫" + name + ",今年" + age + "岁了,家住" + address + ",汪汪汪...");
} //其他代码...
}

请注意Dog类的say()方法,直接访问了nameage属性,如果子类继承了父类的私有成员,那么这样写是没问题的,但事实是nameage报红了,说明子类没有继承父类的私有成员。

虽然子类没有继承父类的私有成员,但是我们可以通过父类的公有方法使用其私有成员变量,代码改动如下:

public class Dog extends Animal {

    private String address;

	public void say() {
System.out.println("我叫" + super.getName() + ",今年" + super.getAge() + "岁了,家住" + address + ",汪汪汪...");
} //其他代码...
}

使用super.xxx()可以调用父类的方法,由于getName()是父类公有方法,且能访问父类的私有成员变量name,所以子类调用getName()方法可以使用name变量。

3.4. 子类如何对父类的私有成员赋值?

子类没有继承父类的私有成员变量,当然不能直接赋值。通常有两种方法:调用父类的公有setter方法或调用父类的构造器。本质上还是子类通过使用父类提供的公有方法(setter或构造器)使用其私有成员变量。

3.4.1. 使用setter方法:

public class Dog extends Animal {

    private String address;

    public void setName(String name) {
super.setName(name); //注意super
} public void setAge(int age) {
super.setAge(age);
} public void say() {
System.out.println("我叫" + super.getName() + ",今年" + super.getAge() + "岁了,家住" + address + ",汪汪汪...");
} //其他代码...
}

Dog类的两个setter方法调用了Animal类的两个setter方法,由于子类的setter方法名和父类的setter方法名取得一样(重写了),所以一定要使用super关键字加以区分,否则就成递归了。

3.4.2. 调用父类的构造器:

public class Dog extends Animal {

    private String address;

    public Dog(String name, int age, String address) {
super(name, age); //调用父类构造器
this.address = address;
} public Dog() {
} public void say() {
System.out.println("我叫" + super.getName() + ",今年" + super.getAge() + "岁了,家住" + address + ",汪汪汪...");
} //其他代码...
}
public class Animal {
private String name;
private int age; public Animal(String name, int age) {
this.name = name;
this.age = age;
} //其他代码...
}

子类使用super()语句调用父类构造器,该语句必须是子类构造器的第一行代码。

如果子类构造器没有显式调用父类构造器,则会默认调用父类的无参构造器。所以如果父类没有无参构造器,而子类又没有显式调用父类的其他构造器,则会报错。

4. 关于我

如有错误,还请指正。

一文打尽Java继承的相关问题的更多相关文章

  1. java继承属性相关介绍

    这个只需要记住一点,父类的任何属性(变量可以看做属性),子类均可继承并覆盖,allType(father)-->changeAnyType(son)-->AnyType 这是父类的所有代表 ...

  2. 一文打尽Java抽象类和接口的相关问题

    相关文章: <面向对象再探究>:介绍了面向对象的基本概念 <详解Java的对象创建>:介绍了对象的创建.构造器的使用 <一文打尽Java继承的相关问题>:介绍了继承 ...

  3. Java继承相关知识总结

    Java继承的理解 一.概念: 一个新类从已有的类那里获得其已有的属性和方法,这种现象叫类的继承 这个新类称为子类,或派生类,已有的那个类叫做父类,或基类 继承的好处:代码得到极大的重用.形成一种类的 ...

  4. 【Java初探01】——Java简介及相关

    Java 简介 java 是一种高级的面向对象的程序设计语言,使用Java语言编写的程序时跨平台的.从pc到手机,都有Java开发的程序和游戏,Java程序可以在任何计算机,操作系统和支持的Java的 ...

  5. JAVA继承时构造函数的问题

    今天看到java继承部分时,关于构造函数是否继承以及如何使用时遇到了点问题,后来查找相关资料解决了. 下面是我个人的总结: 先创建一个父类,里面有两个构造函数: public class Jisuan ...

  6. 【Socket编程】Java中网络相关API的应用

    Java中网络相关API的应用 一.InetAddress类 InetAddress类用于标识网络上的硬件资源,表示互联网协议(IP)地址. InetAddress类没有构造方法,所以不能直接new出 ...

  7. Java 继承和多态

                                                        Java  继承和多态 Java 继承 继承的概念 继承是java面向对象编程技术的一块基石,因 ...

  8. 111 01 Android 零基础入门 02 Java面向对象 04 Java继承(上)02 继承的实现 01 继承的实现

    111 01 Android 零基础入门 02 Java面向对象 04 Java继承(上)02 继承的实现 01 继承的实现 本文知识点: 继承的实现 说明:因为时间紧张,本人写博客过程中只是对知识点 ...

  9. 「万字图文」史上最姨母级Java继承详解

    摘要:继承是面向对象软件技术中的一个概念.它使得复用以前的代码非常容易,能够大大缩短开发周期,降低开发费用. 本文分享自华为云社区<「万字图文」史上最姨母级Java继承详解丨[奔跑吧!JAVA] ...

随机推荐

  1. postman-4-响应内容

    通过响应报文来检测接口的正确性:响应由正文,响应头和状态码组成 Pretty模式可以格式化JSON或XML响应报文,以便更容易查看.突出显示Pretry模式中的链接,点击它们, 可以通过链接URL在P ...

  2. Centos 6.4最小化安装后的优化(1)

    一.更新yum官方源 Centos 6.4系统自带的更新源速度比较慢,相比各位都有所感受,国内的速度慢的让人受不了.为了让centos6.4系统使用速度更快的yum更新源,一般都会选择更换源,详细步骤 ...

  3. Charles抓包工具操作指南

    一.Charles说明 Charles是HTTP代理/ HTTP监视器/反向代理,使开发人员或测试人员可以查看其计算机与Internet之间的所有HTTP和SSL/ HTTPS通信. 这包括请求,响应 ...

  4. Ubuntu systemctl 查看管理系统启动项

    Ubuntu systemctl 查看系统启动项 列出所有启动项: sudo systemctl list-unit-files 会列出开启的和未开启的: 使用grep过滤一下开启的grep enab ...

  5. tensorboard学习笔记

    TensorBoard 默认是不会记录每个节点的用时.耗费的内存大小等这些信息的,那么如何才能在图上显示这些信息呢?关键就是如下这些代码,主要就是在 sess.run() 中加入 options 和  ...

  6. spring security简单登录的认证

    一.思路 1.先导入相关配置(使用spring security校验之后,登录拦截的配置) 2.创建一个 WebSecurityConfig 继承 WebSecurityConfigurerAdapt ...

  7. CSS上划线、下划线、删除线等方法

    text-decoration:underline;     下划线 text-decoration:overline;    顶划线 text-decoration:line-through;  删 ...

  8. Ethical Hacking - GAINING ACCESS(7)

    Server Side Attacks - NEXPOSE NeXpose is a vulnerability management framework, it allows us to disco ...

  9. 什么是CSV

    逗号分隔值(Comma-Separated Values,CSV,有时也称为字符分隔值,因为分隔字符也可以不是逗号),其文件以纯文本形式存储表格数据(数字和文本).纯文本意味着该文件是一个字符序列,不 ...

  10. 郭的手机出现提示:条码扫描器,抱歉,Android相机出现问题。您可能需要重启设备

    郭的手机出现提示:条码扫描器,抱歉,Android相机出现问题.您可能需要重启设备 ++++++++++++++++++ 原因是系统没有给应用使用摄像头的权限,我到楼下设置对方手机,选择“设置”-&g ...