Java面向对象(2) —— 继承

目录

  • 前言
  • 继承的概念和实现
    • extends关键字
    • super关键字
    • 继承过来的属性和方法的权限研究
    • 方法重写Override
  • Object根类常见方法
    • toString()
      • 常把toString()方法重写后应用
    • equals()
      • 重写:判断两个对象p1和p2特征是否相同
      • IDEA的重写模板:敲equals可选择的方案之一
      • String 类重写:判断字符串是否相等
  • 继承练习:java面向对象下的简单工厂模式

前言

下面C语言的代码中定义了两个在内容上高度重复的结构体

#include <stdio.h>struct Person  //人
{int name;char* address;void (*pEat)();  void (*pDrink)();
};struct Student //学生也是人,所以有一定的重复性
{             int name;char* address;void (*pEat)();void (*pDrink)();int score; //学生独有的特征,有分数,要上学void (*goToSchool)();
};

然而对于C语言来说这两个结构体没有任何联系,这样造成了代码的浪费,重复。

而java的继承特性,就解决了这一问题。

继承的概念和实现

生活中,继承的概念随处可见。

比如:

在这里插入图片描述

java继承背后的思想是:基于已存在的类来构建新类。

当从已存在类继承时,就重用了他的方法和属性,还可以添加新的方法和属性来定制新类以应对要求。

继承的意义:代码重用,体现不同抽象层次

约定:从其他类导出的类叫做子类,通常父类更通用更抽象,子类更特殊更具体。

在java中,除了object外,所有类都是子类,都只有唯一的父类,即为object类。

所以继承在OOP(Object-Oriented Program面向对象编程 )中不可或缺,创建一个类时,总是在继承

extends关键字

在java语言中,用extends关键字来表示一个类继承了另一个类,如Student继承了Person

public class Student extends Person{
...
}
  • 1
  • 2
  • 3

例子:

class Person {String name;String address;void eat() {System.out.println("人吃饭");}void drink() {System.out.println("人喝水");}
}class Student extends Person{ //可以直接使用Person中的属性了int score;void goToSchool() {System.out.println("学生要上学");}
}public class Demo1 {public static void main(String[] args) {Person p = new Person();p.name = "人";p.eat();Student s = new Student();s.name = "学生";  //person中的特征s.eat();         //person中的方法}
}

super关键字

super和this关键字的特点类似:super代表的是对父类对象的引用

作用:

(1)当子父类的成员出现同名时,可以通过super来区分
(2)子类的构造方法中,通过super关键字调用父类的构造方法

强调:

(1)当构造一个子类对象的时候一定会先调用父类的构造方法来构造父类的对象。
(2)调用父类构造方法的语句必须是子类构造方法中的第一条指令

super关键字的例子:

class Person {String name;String address;void eat() {System.out.println("人吃饭");}void drink() {System.out.println("人喝水");}//Person(){}//解决方法一:在父类中写一个无参的构造方法Person(String name,String address){//构造方法给属性赋初值this.name = name;this.address = address;System.out.println("父类构造方法被调用");}
}class Student extends Person{ //可以直接使用Person中的属性了int score;void goToSchool() {System.out.println("学生要上学");}/*Student(){ //如果不写父类中已有的构造方法的话,系统分配类似于这样的无参构造方法//如果父类写了构造方法而子类没有“对应的”构造方法,就会出错//解决方法一:在父类中写一个无参的构造方法;//解决方法二:应用super关键字,在子类中完成对父类构造方法的引用}*/         //父类可能有多个构造方法,子类只需要引用一个初始化自己就好//解决方法二:Student(String name,String address){ //没有下面的super的话 系统不认定这是一个构造方法super(name, address); //调用了父类的构造方法,这个语句必须放在子类构造方法的第一句System.out.println("子类构造方法被调用");}public void eat(){ //因为父类已经有了方法eat,这里权限不能降低,所以加public,后面讲多态会介绍:方法的重写super.eat(); //调用父类的eat,super是对父类的引用。//子类中有eat,父类也有同名的方法,如何区分是父类还是子类的eat,用super!System.out.println("student eat");}
}public class Demo1 {public static void main(String[] args) {//在实例化一个对象的时候,子类的构造方法调用会导致父类的构造方法也被调用:Student s = new Student("小明","西祠胡同1号");s.eat();}
}

结果:

父类构造方法被调用
子类构造方法被调用
人吃饭
student eat

父类的地址:西祠胡同1号

继承过来的属性和方法的权限研究

重点看看父类中的私有属性private会不会被子类继承,如果可以,显然其他的默认属性如public、默认等肯定也可以。

class Person {String name;private String address;  //私有的属性void eat() {System.out.println("人吃饭");}Person(String name,String address){this.name = name;this.address = address;System.out.println("父类构造方法被调用");}    
}class Student extends Person{int score;void goToSchool() {System.out.println("学生要上学");}Student(String name,String address){super(name, address); //调用了父类的构造方法 可以间接的访问到父亲的address!}/*void setAddress(String address){this.address = address; //这里提示了address是父类私有的,说明实际上没有被继承过来                //不给你用,父亲”私藏的“所有东西儿子都是不知道的,继承不到}*/
}

结论:父类私有的无论是方法还是属性,都无法被子类继承。

方法重写Override

方法重写是指子类可以根据需要对从父类继承过来的方法进行改写,是多态机制的前奏。

(1)重写方法必须和被重写方法具有相同的方法名称、参数列表和返回值
(2)重写方法不能比被重写方法有更严格的访问权限
(3)父类中的私有方法,不能被重写
(4)在子类重写的方法中继承调用父类被重写的方法可以通过super.函数名获取

注意区别:前面封装部分提到的方法重载是同一方法名,不同参数列表。而重写的话则全部都是一样的,包括函数名、参数、返回值。

例子:

class Person
{String name;private String address;public void printName(){System.out.println("name="+name);}private void printAddress(){   //父类的私有方法,想要"重写"这个方法,子类中的方法不能是privateSystem.out.println("address="+address);}
}class Student extends Person
{int score;public void printName() { //(1)重写方法必须和被重写方法具有相同的名称、参数列表和返回值//(2)重写方法不能比被重写方法有更严格的访问权限System.out.println("子类name=" + name); //方法的实现改了,也是重写啊,别看就改了一点}public void printAddress(){             //如果这里用的是private,那下面的stu1.printAdd就会报错System.out.println("想用你的私有方法");//注意:如果父类方法权限是private,子类不能用private去重写这个方法}                                       //这对于子类来说,父类是不可见的,是看不到父类的方法的
}                                           //所以这对于子类来说,就是【构造了一种新的方法】,既不是方法重写也不是方法重载!//是不是重写,就概念的东西,初学,也不必争辩,知道这么用就行
public class Demo1 {public static void main(String[] args){Student stu1 = new Student();stu1.name = "小明";stu1.printName();stu1.printAddress();   }
}

运行结果:

子类name=小明	
想用你的私有方法            //说明子类对父类私有方法的重写 “成功” 

Object根类常见方法

java中,所有类都直接或间接继承自java.lang.Object类,是所有类的根类。如hashcode()、clone()、getClass()、finalize()。

重点介绍下面两类toString()equals()

toString()

做个简单的测试:

package com.huatianzhu.learn;class Person
{String name;
}public class Demo1 {public static void main(String[] args) {Person p = new Person();p.name = "huatianzhu";System.out.println(p.toString());}
}

结果

com.huatianzhu.learn.Person@49e4cb85
  • 1

为什么会是上面的结果?

返回格式:

getClass().getName()+"@"+Integer.toHexString(hashCode());
  • 1

(1)getClass().getName()代表返回对象所属类的包名.类名,即com.huatianzhu.learn
(2)Integer.toHexString(hashCode())代表将对象的哈希值用16进制表示,其中hashCode()代表返回该对象的哈希值。

常把toString()方法重写后应用

然而,在实际开发中,通常希望toString()方法返回的不只是上面的信息,所以Object的toString()方法通常会被重写,如下:

@Override
public String toString() {return "Person{" +"name='" + name + '\'' +", address='" + address + '\'' +'}';
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

(这是IDEA的重写方案:自动补全后就跳出来了如上代码)

运行结果:使得toString()根据实际需求打印出信息

Person{name='huatianzhu', address='null'}
  • 1

equals()

equals方法没有重写的话,用于判断对象的内存地址引用是否使用一个地址。重写之后一般用来比较对象的内容是否相等(比如student对象,里面有姓名和年龄,我们重写,判断这两个对象是相等的

重写:判断两个对象p1和p2特征是否相同

package com.huatianzhu.learn;import java.util.Objects;class Person {String name;String address;public boolean equals(Person p){//传对象参数//Person p = (Person)arg0;不给这样做强换if(this.address == p.address && this.name == p.name)//C语言比较字符串使用strcmp()return true;elsereturn false;}
}public class Demo1 {public static void main(String[] args) {Person p1 = new Person();p1.name = "xiaoming";p1.address = "西祠胡同1号";Person p2 = new Person();p2.name = "xiaoming";p2.address = "西祠胡同1号";System.out.println(p1.equals(p2));}
}

运行结果

true
  • 1

IDEA的重写模板:敲equals可选择的方案之一

package com.huatianzhu.learn;import java.util.Objects;class Person {String name;String address;//下面两个override都是IDEA自带的重写模板@Overridepublic boolean equals(Object o) {if (this == o) return true;if (!(o instanceof Person)) return false;Person person = (Person) o;return Objects.equals(name, person.name) &&Objects.equals(address, person.address);}@Overridepublic int hashCode() {return Objects.hash(name, address);}
}public class Demo1 {public static void main(String[] args) {Person p1 = new Person();p1.name = "xiaoming";p1.address = "西祠胡同1号";Person p2 = new Person();p2.name = "xiaoming";p2.address = "西祠胡同1号";System.out.println(p1.equals(p2));}
}

运行结果

true
  • 1

String 类重写:判断字符串是否相等

String 类中重写了 equals() 方法用于比较两个字符串的内容是否相等。

语法:public boolean equals(Object anObject)

实例:

public class Test {public static void main(String args[]) {String Str1 = new String("huatianzhu");String Str2 = Str1;  //直接把 对象1 赋值给 对象2 String Str3 = new String("chenlichen");boolean retVal;retVal = Str1.equals( Str2 );System.out.println("返回值 = " + retVal );retVal = Str1.equals( Str3 );System.out.println("返回值 = " + retVal );}
}

运行结果:

返回值 = true
返回值 = false
  • 1
  • 2

继承练习:java面向对象下的简单工厂模式

之前做智能家居项目的时候,用了C语言的链表,做了简单工厂模式。在java中感受一下,这面向对象(主要是继承)的魅力。免除了C语言中在工厂链表增加节点的模式,其实底层的实现机制也是类似链表。

abstract class Device         //抽象类,abstract后面也会有介绍
{String open;String close;void init(){System.out.println("设备的初始化");}abstract void diffFunction(); //抽象方法,不同设备有不同的使用方法,不好在//这个大的类进行规划,所以做得抽象点Device(String cmd1,String cmd2){this.open = cmd1;         //设备的开关指令this.close = cmd2;}
}class Camera extends Device
{Camera(String cmd1,String cmd2){super(cmd1,cmd2);      //当父类有构造方法时(非空),子类必须调用父类的}                          //构造方法进行属性的初始化void diffFunction(){System.out.println("相机拿来拍照"); //对抽象方法的具体化,相机是拿来拍照的}                                   //也必须具体化,否则这个继承的子类也要修饰成抽象类/*public void takePhoto(){System.out.println("拍了张张片"); //每个设备不一样的功能可以在其父类Device中进行方法的抽象} */                                //然后在子类中进行具体化,这是面向对象很方便的地方
}class Lightone extends Device
{Lightone(String cmd1,String cmd2){super(cmd1,cmd2);}void diffFunction(){System.out.println("第一个灯拿来照亮卧室");}/*void printInfo(){System.out.println("灯1额外执行的东西");}*/
}class Lighttwo extends Device
{Lighttwo(String cmd1,String cmd2){super(cmd1,cmd2);}void diffFunction(){System.out.println("第二个灯拿来照亮浴室");}/*void printInfo(){System.out.println("灯2额外执行的东西");}*/
}class Factory
{                                          //返回值是对象Device的方法static Device getDevice(String name){  //作为静态方法,不用依靠Factory创建的对象访问if(name == "相机"){return new Camera("open-c1","close-c1");//因为Device是抽象的,不可实例化}                                           //但其继承这个抽象类的类,使用时必须实例化else if(name == "灯1"){                     //所以此处方法返回类型写的是Device,但返回了具体的实例对象//这也是以后会讲解到的多态。return new Lightone("open-d1","close-d1");}else if(name == "灯2"){return new Lighttwo("open-d2","close-d2");}elsereturn null;}
}public class Test {public static void main(String[] args) {Factory.getDevice("相机").diffFunction();//通过名字找到子类,并调用子类的功能方法Factory.getDevice("灯1").diffFunction();//是不是像极了C语言的工厂模式,从链表中找设备Factory.getDevice("灯2").diffFunction();}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/265783.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux下达梦数据库启动_linux 平台 达梦DM 7 数据库 启动与关闭

在之前的博客我们了解了Linux 平台下DM7的安装&#xff0c;如下&#xff1a;在本篇博客里我们了解一下DM7的启动和关闭。1 背景知识说明1.1 DM DB的启动过程DM的启动主要按如下三个步骤进行&#xff1a;1.读取配置文件(.ini)2.读取控制文件(dm.ctl)3.读取重做日志文件(.log) 和…

a与a:link、a:visited、a:hover、a:active

起因&#xff1a; a与a:link的CSS代码处&#xff0c;忽觉茫茫然不知所以然&#xff1a;这a的CSS和a:link什么关系&#xff1f;貌似有些冲突啊&#xff1f;还有这a:link、 a:visited、a:hover、a:active伪类之间有没有相互制约和继承关系&#xff1f; 过程&#xff1a; 使用软件…

dpdk18.11 收发包流程分析

pci probe RTE_PMD_REGISTER_PCI(net_ixgbe, rte_ixgbe_pmd); 宏注册了net_ixgbe driver到pci bus rte_ixgbe_pmd 的定义如下 static struct rte_pci_driver rte_ixgbe_pmd {.id_table pci_id_ixgbe_map,.drv_flags RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,.pr…

人工智能芯片龙头之一gti概念股_AI芯片龙头寒武纪IPO价格定了!概念股全名单收好...

寒武纪披露首次公开发行股票并在科创板上市发行公告&#xff0c;确定发行价格为64.39元/股&#xff0c;本次科创板上市发行剔除无效报价和最高报价后剩余报价拟申购总量为3,405,910万股&#xff0c;整体申购倍数为回拨前网下初始发行规模的1327.12倍。战略配售投资者包含中信证…

x86汇编语言-从实模式到保护模式----第五章

注释由;开始。将显存映射到地址空间里&#xff0c;0xB8000~0xBFFFF。Intel的处理器不允许将一个立即数传送到段寄存器&#xff0c;只允许这样的指令&#xff1a;mov 段寄存器&#xff0c;通用寄存器 mov 段寄存器&#xff0c;内存单元 为了方便&#xff0c;多数汇编语言编译器允…

Java面向对象(3) —— 抽象类、接口、内部类、匿名内部类

目录抽象类&#xff08;abstract&#xff09;抽象类的使用方法抽象类的应用&#xff1a;模板方法模式接口接口的概念接口的特点接口的使用接口实现与抽象类继承的区别接口的多继承内部类概念成员内部类&#xff08;使用较多&#xff09;及应用创建成员内部类的实例在成员内部类…

Kohana和Zencart

2019独角兽企业重金招聘Python工程师标准>>> 我有一个Kohana php框架但是客户求和zencart系统结合。我有一个想法是Kohana重新zencart 有没有人用过&#xff1f;应该没有吧 Kohana 是一款纯 PHP5 的框架&#xff0c;基于 MVC 模式开发&#xff0c; 它的特点就是高安…

Linux stmac网卡代码分析 -- open

Open stmmac_open是在stmmac_netdev_ops结构体里的&#xff0c;这个ops在probe时就已经注册到了net_device结构体里&#xff0c;在网卡对于stmmac_open函数调用的时间我还不确定是否是在网卡link up时 下面看看stmmac_open函数&#xff0c;文件位置&#xff1a; drivers/net/…

g++ linux 编译开栈_方舟编译器编译hello world踩坑全记录

闲来无事&#xff0c;看到方舟编译器完整开源&#xff0c;于是打算拿来试着编译一个东西来&#xff0c;接下来把踩过的一些坑记录一下。参考文档方舟编译器的官网是OpenArkCompiler​www.openarkcompiler.cn但是这个网站上的文档其实是过时的&#xff0c;没有更新过的&#xff…

绘制自定义键盘

先看下微信当中的自带的数字键盘 这种实现方式比较简单&#xff0c;可以直接用inline-block标签&#xff0c;设置每行平均宽度&#xff0c;比如一行要放4个按钮&#xff0c;可以那么宽度就可以设为25%&#xff0c;同时要注意设置css样式为box-sizing: border-box,这样在设置边框…

配置管理小报100329:脚本中ftp命令无法自动输入密码怎么办?

为什么80%的码农都做不了架构师&#xff1f;>>> 知识点&#xff1a; 作者&#xff1a;王&#xff08;zbwangjian.cn&#xff09; 脚本中ftp命令无法自动输入密码怎么办&#xff1f;参考&#xff1a; http://www.linji.cn/post/1620/ http://www.hamo…

linux下使用网易邮箱发邮件

0x0 最近要写个脚本监视系统运行情况&#xff0c;有异常及时通过邮件通知我。 本次测试中使用网易的邮箱作为邮件发送服务器&#xff08;邮箱账号需要开启smtp服务如下图&#xff09;&#xff0c;由于网易邮箱验证比较严格&#xff0c;需要进行一些额外操作才可以正常发送邮件…

Java面向对象(4) ——多态

目录多态的概念对象上下转型多态应用之打印机多态的概念 多态是指同一个操作作用于某一类对象&#xff0c;可以有不同的解释&#xff0c;产生不同的执行结果。比如&#xff1a;猫吃鱼、狗吃肉、人吃米饭。 多态存在的三个必要条件: 需要存在继承&#xff08;extends&#xf…

ffmpeg 转换flv压缩大小_ffmpeg转换参数和压缩输出大小的比率 参考 最新版本FFMPEG...

https://blog.cnlabs.NET/3668.htmlffmpeg 转换压缩比例FFMPEG如果是压缩为FLV文件 3个编码可选1. -c:v flv 标准FLV编码 这个好处是速度快 清晰度高的话 视频文件会比较大2. -c:v vp6 VP6编码 这个大家都很少使用 其实这个也算不错3. -c:v libx264 H.264编码 估计使用这个的比…

Git 常用命令清单,掌握这些,轻松驾驭版本管理

GitHub 地址&#xff0c;欢迎star&#xff0c;查看更多整理的前端知识点 工程下载、分支的增删查改 工程下载&#xff1a; clone 远程工程&#xff1a;git clone https://XXXX.gitfetch 远程分支到本地某分支&#xff1a;git fetch origin <orginname>:<localname>…

【运维囧事】运维的苦乐之旅

人生就是一段充满苦与乐的旅程&#xff0c;在人生当中有痛苦也有欢乐&#xff0c;痛苦不一定是负面的&#xff0c;有的时候还会使你进步&#xff0c;增强应变能力。对一般人而言&#xff0c;人生一定要是快乐的才是有意义的&#xff0c;可是你仔细想想&#xff0c;有谁不是因为…

ubuntu下网易云音乐适配高分辨率屏幕

0x0 环境 ubuntu20处理器 AMD 我主流工作环境是Ubuntu20&#xff0c;而且很依赖音乐&#xff0c;网易云音乐适配了Ubuntu&#xff0c;而最近我换了个4K屏幕 开机启动网易云音乐后发现界面文字变得很小完全没法看&#xff0c;如下图 分析发现网易云音乐是通过 /opt/netease/ne…

Java基础 —— 异常

目录异常的概念及分类异常的处理try-catch-finally异常抛出throw(s)自定义异常异常的概念及分类 什么是异常 异常是指在程序的运行过程中发生的一些不正常事件。比如&#xff1a;除0溢出、数组下标越界、所要读取的文件不存在。 异常导致的后果 项目JAVA程序的执行过程中如出现…

excel函数去重_excel去重函数

在日常工作问题中&#xff0c;经常会遇到一个问题&#xff0c;当你呼哧呼哧处理了大半天的数据后才发现&#xff0c;原始数据好多重复的&#xff0c;导致你得到的结果全部错误……顿时&#xff0c;想砍人的心都有了&#xff0c;心理阴影面积无穷大……当然&#xff0c;胖斯基也…

解决网站请求速度慢的一些方法

开门见山&#xff0c;网站请求反应速度慢首先考虑服务器问题。 我在开发中遇到的就是服务器实例限制cpu占用10%以内访问正常&#xff0c;超出则限制访问速度&#xff0c;也就是网站请求速度慢 具体和阿里工程师聊天截图如下&#xff1a; 按照对方说的&#xff0c;升级了相关配置…