Extend继承

继承的作用

当我们定义了一个Person类:

class Person{private Stirng name;private int age;public String getName(){....}public int getAge(){...}public void setName(String name){...}public void setAge(int age){...}
}

现在,假设还需要定义一个Student类:

class Student{private Stirng name;private int age;private int score;public String getName(){....}public int getAge(){...}public int getScore(){...}public void setName(String name){...}public void setAge(int age){...}public void setScore(int score){...}
}

        通过观察我们发现这两个类相似,其中Student类包含了Person类中已有的字段和方法,只是多了一个score字段和相应的set、get方法。那能不能不用在Student类中写重复的代码呢?这时候我们就需要用继承(Extends)来解决这个问题。

        继承是面向对象编程中非常强大的一种机制,首先它可以实现代码的复用,当Student类继承Person类时,Student类就获得了Person的所有功能,我们只需要为Student类添加一些其他我们想实现的功能。在Java中我们用关键字extends来实现继承:

class Person{private Stirng name;private int age;public String getName(){....}public int getAge(){...}public void setName(String name){...}public void setAge(int age){...}
}
class Student extends Person{private int score;public int getScore(){...}public void setScore(int score){...} 
}

注意:子类自动获得父类的所有字段,严谨定义与父类重名的字段

        在我们定义Person的时候,没有写extends。在java中,没有明确写extend的类,编译器会自动加上extends Object。所以,任何类,除了Object,都会继承自某个类,如下图:

        java只允许一个类继承自一个类,因此,一个类有且仅有一个父类。只有Object特殊,他没有父类。

protected关键字

        继承有一个特点,就是子类无法继承父类的private字段或者private方法。例如,Student类无法访问Person类的name和age字段,这样,继承的作用就会被削弱。为了让子类可以访问父类的字段,我们需要把修饰符从private改为protected。用protected修饰的字段可以被父类访问

super关键字

        super关键字表示父类(超类),子类引用父类的字段时,可以用super.fieldName,例如:

public class Person {protected String name;private int age;}
class Student extends Person{public String hello() {//子类允许访问父类protected修饰的成员变量和方法return "hello"+super.name;}
}

        实际上,这里使用super.name,或者this.name ,或者直接使用name的效果都是一样的。编译器会自动定位到父类的name字段。但是在某些时候,必须使用super:

public Main{public static void main(String[] args){Student s=new Student("Wei",18,100);}
}
class Person{protected String name;protected int age;public Person(String name,int age){this.name=name;this.age=age;}
}
class Student extends Person {protected int score;public Student(String name,int age,int score){this.score=score;}
}

        运行此代码,会得到一个编译错误,大意是在Student的构造方法中无法调用Person的构造方法。

        因为在Java中,任何子类的构造方法,第一句语句必须是调用父类的构造方法。如果没有明确的调用父类的构造方法,编译器会帮我们自动加一句super(),所以,Student的构造方法实际应该是这样的:

public Main{public static void main(String[] args){Student s=new Student("Wei",18,100);}
}
class Person{protected String name;protected int age;public Person(String name,int age){this.name=name;this.age=age;}
}
class Student extends Person {protected int score;public Student(String name,int age,int score){super();//自动调用无参构造方法this.score=score;}
}

        但是,在这个实例中,我们没有在父类中定义一个无参的构造方法,因此依然编译失败。解决方法是:手动调用Person类存在的某个构造方法,这样就可以正常编译了:

public Main{public static void main(String[] args){Student s=new Student("Wei",18,100);}
}
class Person{protected String name;protected int age;public Person(String name,int age){this.name=name;this.age=age;}
}
class Student extends Person {protected int score;public Student(String name,int age,int score){super(name,age);//手动调用有参构造方法this.score=score;}
}

        由此,我们可以得出结论:如果父类没有默认的构造方法,子类必须显式的通过super关键字,让编译器定位到某个合适的构造方法。

        这里还顺带引出了另一个问题:即子类不会继承任何父类的构造方法。子类默认的构造方法是编译器自动生成的,而不是继承父类的。

简单应用

我们用一个有更完整功能的实例来加深一下对继承的理解:

//商品类(父类)
clas Product{//成员变量private double price;private int stock;//无参构造方法public Product(){}//有参构造方法public Product(double price,int stock){this.price=price;this.stock=stock;}//getter和Setter方法public double getPrice() {return price;}public void setPrice(double price){if(price<=0){this.price=0.01;}else{this.price = price;}}public int getStock() {return stock;}public void setStock(int stock) {this.stock = stock;}}
//图书类(子类)
class Book extends Product{private String bookName;private String author;//构造方法public Book(String bookName,double price,String author,int stock)){this.bookName=bookName;this.author=author;super.setPrice(price);super.setStock(stock);}@Overridepublic String toString() {return String.format("书名:《%s》,作者:%s,价格:¥%f,库存:%d",				this.bookName,this.author,super.getPrice(),super.getStock());}
}//手机类(子类)
class Phone extends Product{private int memory;private String model;public Phone(String model,int memory,double price,int stock) {                                                                                                                                                                                                                                                                                                                                 //方法一:通过父类的set和get方法,保存库存和价格
//  super.setPrice(price);
//  super.setStock(stock);//方法二:通过父类有参的构造方法,保存库存和价格super(price,stock){this.memory=memory;this.model=model;}@Overridepublic String toString() {return String.format("型号:%s,价格:¥%f,内存:%dG,库存:%d"			            this.model,super.getPrice(),this.memory,super.getStock());}
}
public class Test {public static void main(String[] args) {Phone phone1=new Phone("Mate60",8888,128,67);Book book1=new Book("皮皮鲁和鲁西西",12.5,"李",80);System.out.println(book1);System.out.println(phone1);}}

输出结果:

向上转型

        如果引用变量的类型是Student,它可以指向一个Student类型的实例:

Student s=new Student();

         如果引用变量的类型是Person,它可以指向一个Person类型的实例:

Person p=new Person();

        如果Student是从Person继承下来的,一个引用类型为Person的变量,它可以直接指向Student类型的实例:

Person p=new Student();

        因为Student继承自Person,因此,它拥有Person的全部功能。所以Person类型的变量,如果指向Student类型的实例,对他进行操作是没有问题的。这种把一个子类类型安全地变为父类类型的赋值,称为向上转型(upcasting)

        向上转型实际上是把一个子类安全地变为更抽象的父类类型,继承树的顺序是:Student->Person->Person->Object。所以可以把Student转换为Person类型,或者更高层次的Object。

Student s=new Student();
Person p=s;
Object o1=p;
Object o1=s;

向下转型

        和向上转型相反,如果把一个父类类型强制转换为子类类型,就是向下转型(downcasting)。例如:

Person p1=new Student();//向上转型
Person p2=new Person();
Student s1=(Student)p1;//ok
Student s2=(Student)p2;//runtime error! ClassCastException!

        运行时,Person类型实际上指向Student实例,p2指向Person实例,所以在进行向下转型时,p1转型为Student会成功,是因为p1本身指向Student实例p2转为Student会失败,是因为p2没有指向Student,而是指向Person,不能将父类变为子类,因为子类的方法可能比父类方法多,多的方法不能凭空变出来,因此向下转型会失败,会报ClassCastException异常。

        为了避免向下转型失败,Java提供了instanceof操作符,可以先判断这个实例是不是某种类型,再进行向下转型:

Person p=new Person();
System.out.println(instanceof Person);//true
System.out.println(instanceof Student);//falseStudent s-new Student();
System.out.println(instanceof Student);//true
System.out.println(instanceof Person);//falsePerson p=new Student();
if(p.instanceof Student){//只有判断成功才会向下转型Student s=(Student)p;//一定转型成功
}

综合应用

//父类
class Computer{private String cpu;//中央处理器private int ssd;//固态硬盘//无参构造方法public Compuetr(){}//有参构造方法public Compuetr(String cpu,int ssd){this.cpu=cpu;this.ssd=ssd;}
}
//子类:PC机
class PersonComputer extends Computer{private String displayCard;//显卡//构造方法public PersonComputer(String cpu,int ssd,String displayCard) {//手动调用父类的有参构造方法super(cpu,ssd);this.displayCard=displayCard;}public String getDisplayCard() {return displayCard;}public void setDisplayCard(String displayCard) {this.displayCard = displayCard;}}
//子类:笔记本电脑
class NotebookComputer extends Computer{private String brand;//品牌public NotebookComputer(String cpu,int ssd,String brand) {//手动调用父类的有参构造方法super(cpu,ssd);this.brand=brand;}public String getBrand() {return brand;}public void setBrand(String brand) {this.brand = brand;}}
public class Computer_test {public static void main(String[] args) {//对象数组//类型如果是父类,代表数组内可以保存任意一种子类的对象Computer[] array={new Computer("Intel i8",127),new PersonComputer("Intel i9",128,"8090Ti")new NotebookComputer("AMD R9",512,"联想"),new NotebookComputer("AMD R9",512,"小米"),new PersonComputer("Intel i9",128,"4090T")};for(int i=0;i<array.length;i++){//获取数组中的元素Computer comp=array[i];//向下转型//instanceof运算符://判断当前引用comp指向的对象类型是否是PersonComputerif(comp instanceof PersonComputer){PersonComputer pc=(PersonComputer)cmp;System.out.println("台式机的显卡型号是:"+pc.getDisplayCard());}else if(comp instanceof NotebookComputer){NotebookComputer nb=(NotebookComputer)comp;System.out.println("笔记本的品牌是:"+nb.getBrand());}}
}

输出结果:

台式机的显卡型号是:8090Ti
笔记本的品牌是:联想
笔记本的品牌是:小米
台式机的显卡型号是:4090Tipluse

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

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

相关文章

多目标粒子群(MOPSO)算法原理及其MATLAB实现

粒子群算法(PSO)是Eberhart和Kennedy于1995年提出的一种模拟鸟类觅食行为的算法[1]&#xff0c;具有操作简单、速度快等特点。但在实际应用中&#xff0c;许多决策问题都是多目标优化问题&#xff0c;采用粒子群算法来处理多目标优化问题是一种有效方法&#xff0c;Coello 等人…

URL输入到页面渲染过程详解

当我们在浏览器中输入一个URL并按下回车键时&#xff0c;浏览器会执行一系列步骤来解析URL、发送请求、接收响应&#xff0c;并最终渲染页面。这个过程涉及到多个阶段&#xff0c;包括DNS解析、TCP握手、发送HTTP请求、服务器处理请求、返回HTTP响应、浏览器解析和渲染等。下面…

Jmeter高效组织接口自动化用例

1、善用“逻辑控制器”中的“简单控制器”。可以把简单控制器像文件夹一样使用&#xff0c;通过它来对用例进行分类归档&#xff0c;方便后续用例的调试和执行。 2、同编写测试用例一样&#xff0c;这里的接口测试用例应该进行唯一性编号&#xff0c;这样在运行整个用例计划出现…

【语法】C++学习

注意 使用devc对vector初始化使用vector v1 {1, 2, 3, 4, 5}; 报错 解决 在编译器选项中加入以下代码 -static-libgcc -stdc11

wince+gprs拨号上网总结

一、硬件连接 本次调试的GPRS模块引脚定义 三星主板全功能扩展串口2引脚定义 因GPRS模块可以和pc机直连进行数据通讯&#xff0c;那么收发肯定内部交叉&#xff0c;故主板和GPRS的连接也采用直连方式。如果接线不对则出现没有回应现象&#xff0c;拨号时出现端口不可用&#xf…

反向代理多级多机

一 架构图 本次实验需要 5台机器 第一台 nginx 只做代理服务器 负责反向代理 加 负载均衡 后面的两台nginx 做真实服务器 处理静态资源 再后面的 tomcat 做真实服务器 处理动态资源 二 具体实验 &#xff08;一&#xff09; 具体实验环境 所有机器关闭防火墙 安装…

System.currentTimeMillis()用法以及计算方式

System.currentTimeMillis()的作用是返回当前的计算机时间&#xff0c;格式为当前计算机时间和GMT时间(格林威治时间)1970年1月1号0时0分0秒所差的毫秒数 比如在做项目时,需要统计下gc操作的执行的消耗时间 除此之外,还可以获取当前的系统时间 //直接把这个方法强制转换成dat…

python创建和上传自己的PyPI库

文章目录 创建和上传自己的PyPI库pypi准备文件制作PyPI包在上传前&#xff0c;先本地验证注册PyPI账户上传pypi判断python包质量之 SourceRankLibraries.io 参考 创建和上传自己的PyPI库 pypi 官方地址&#xff1a;https://pypi.org/ Python中我们经常会用到第三方的包&…

论文阅读:SDXL Improving Latent Diffusion Models for High-Resolution Image Synthesis

SDXL Improving Latent Diffusion Models for High-Resolution Image Synthesis 论文链接 代码链接 介绍 背景&#xff1a;Stable Diffusion在合成高分辨率图片方面表现出色&#xff0c;但是仍然需要提高本文提出了SD XL&#xff0c;使用了更大的UNet网络&#xff0c;以及增…

javaSwing飞机大战

概述 1.1 项目简介 本次Java课程设计是做一个飞机大战的游戏&#xff0c;应用Swing编程&#xff0c;完成一个界面简洁流畅、游戏方式简单&#xff0c;玩起来易于上手的桌面游戏。该飞机大战项目运用的主要技术即是Swing编程中的一些窗口类库、事件监听以及贴图技术。 1.2 实…

【个人账号体系设计】偏个人功能类账号功能模块设计

本文讨论了针对以个人功能为主的业务系统的账号能力设计&#xff0c;包括账号管理的总体需求、关键属性和设计要点。重点在于如何通过细致的设计实现账号的有效管理和安全性&#xff0c;确保系统既便于用户操作又能维持管理的严密性。 文章目录 需求能力模块设计 需求能力 在进…

计算机考研❗️这些院校(含985)性价比巨高

✅厦门大学 (985) 不歧视双非&#xff0c;全靠实力&#xff0c;校园环境还贼美 ✅重庆大学 (985) 信息公开透明&#xff0c;复试抽签 ✅北京师范大学 (985) 不歧视本科出身&#xff0c;面试抽签答题。 ✅东南大学 (985) 保护第一志愿&#xff0c;复试抽签 ✅吉林大学 (…

安捷伦DSA90254A示波器 AgilentDSA90254A

产品简介&#xff1a; •高性能实验室 •2.5 GHz 带宽 •4 个模拟通道&#xff0c;每个通道的采样率为 20 GSa/s •每个通道的数据速率为 20 Mpts 至 1 Gpts •很低的本底噪声&#xff1a;100 mV/格时为 3.01 mVrms •DSA90000A 系列示波器是以 Infiniium DSO90000A 系列…

ChatGPT:人工智能的革命与未来

引言 随着人工智能技术的飞速发展&#xff0c;ChatGPT作为OpenAI推出的一款语言模型&#xff0c;已经引起了广泛的关注和讨论。它不仅改变了我们与机器交流的方式&#xff0c;还为众多行业的发展带来了革命性的影响。本文将深入探讨ChatGPT的技术原理、应用场景以及它对未来的…

JavaEE进阶(14)Linux基本使用和程序部署(博客系统部署)

接上次博客&#xff1a;JavaEE进阶&#xff08;13&#xff09;案例综合练习——博客系统-CSDN博客 目录 程序配置文件修改和打包 构建项目并打包 分平台配置 数据准备 上传jar包到云服务器并运行 开放端口号 验证程序 如何查看日志得到报错信息 常见问题 关于Linux基…

串的匹配算法——KMP算法

目录 一.特点 二.算法思想 三.公式证明 四.next数组及其练习 五.找规律计算next[k] 六.代码实现 一.特点 BF算法的特点是i回退&#xff0c;KMP算法的最大特点是i不回退&#xff0c;由于i不回退&#xff0c;所以KMP算法的时间复杂度是O(nm)。 二.算法思想 在匹配主串和子…

浅谈社会工程学攻击

一、前言 1.1 社会工程学起源 社会工程学是黑客米特尼克在《欺骗的艺术》中所提出&#xff0c;其初始目的是让全球的网民们能够懂得网络安全&#xff0c;提高警惕&#xff0c;防止没必要的个人损失。但在我国黑客集体中还在不断使用其手段欺骗无知网民制造违法行为&#xff0c;…

String类,StringBuilder类,StringBuffer类

前言 String类&#xff0c;StringBuilder类&#xff0c;StringBuffer类都是java提供的定义字符串的类&#xff0c;下面是三种字符串类的异同介绍 String类&#xff1a;String类表示的字符串是是常量&#xff0c;一旦创建内容和长度都无法修改 StringBuilder类&#xff1a;St…

6个维度分析实时渲染和Webgl技术异同

在日常交流中&#xff0c;对Webgl技术熟悉的合作伙伴&#xff0c;在初次了解实时渲染技术时&#xff0c;都会问二者之间的异同。目前很多要求B/S架构的项目&#xff0c;很多在用webgl技术路线&#xff0c;而且这个方案在行业里比较普&#xff0c;业主方对这个也比较熟悉&#x…