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响应、浏览器解析和渲染等。下面…

面视题之——ThreadLocal作用

面视题之——ThreadLocal作用&#xff08;学习中&#xff0c;欢迎纠正&#xff09; 概念 ThreadLocal 是Java中的一个类&#xff0c;它提供了线程局部变量。这些变量与普通变量的区别在于&#xff0c;每个访问该变量的线程都有一个独立的副本&#xff0c;互不干扰。 每一个线…

《Java架构巨头面对全球用户:超大规模系统架构师面试宝典》

随着科技的迅猛发展&#xff0c;Java架构师在构建全球用户服务的大规模系统中扮演着举足轻重的角色。招聘一位卓越的Java架构师&#xff0c;不仅需要深厚的技术功底&#xff0c;更需要面对全球用户和超大规模系统的独特经验。为助您招聘到理想的人才&#xff0c;以下是一份超实…

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

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

批处理(Batch Processing)概念

批处理&#xff08;Batch Processing&#xff09;这一概念在不同上下文中可有不同的含义&#xff1a; 传统操作系统层面&#xff1a; 在早期的操作系统中&#xff0c;批处理是指一种处理模式&#xff0c;用户将一系列作业&#xff08;job&#xff09;按照一定的顺序组织起来&am…

Python算法100例-3.8 黑洞数

1.问题描述2.问题分析3.算法设计4.比较三个数的大小并将其重组5.寻找“黑洞数”6.完整的程序 1&#xff0e;问题描述 编程求三位数中的“黑洞数”。 黑洞数又称陷阱数&#xff0c;是指任何一个数字不全相同的整数&#xff0c;在经过有限次“重排求差”操作后&#xff0c;总会…

【Yarn】error Command failed. Exit code: 1

报错代码 success Installed "create-vue3.9.2" with binaries:- create-vue C:\Program 不是内部或外部命令&#xff0c;也不是可运行的程序 或批处理文件。 error Command failed. Exit code: 1 Command: C:\Program Files\nodejs\node_global\bin\create-vuelate…

【语法】C++学习

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

Vue3搭建后台管理系统模板

1、搭建后台管理系统模板 1.1项目初始化 从0开始搭建一个vue3版本的后台管理系统。一个项目要有统一的规范&#xff0c;需要使用eslintstylelintprettier来对我们的代码质量做检测和修复&#xff0c;需要使用husky来做commit拦截&#xff0c;需要使用commitlint来统一提交规范…

wince+gprs拨号上网总结

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

反向代理多级多机

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

⁴ 在CSDN最火爆的AI话题是这些

CSDN当前AI最热点的文章生成方面的话题是自然语言处理&#xff08;NLP&#xff09;领域中的预训练语言模型&#xff0c;特别是GPT-3模型。 GPT-3&#xff08;Generative Pre-trained Transformer 3&#xff09;是由OpenAI开发的一种基于Transformer架构的大规模预训练语言模型。…

超越脆弱性:用否定法策略优化考研复试准备

很多情况下,你的想象力会为当前的世界添加一些东西。很抱歉,我会在本章中告诉你,这种方法完全是落后的方法:根据脆弱性和反脆弱性的概念,严格来说,正确的想象就是从未来中排除或削减不属于未来的东西,采用否定法,脆弱的事物终将破碎。——《反脆弱:从不确定性中获益》…

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 实…

[C++] 万能引用+引用折叠+完美转发

文章目录 万能引用/通用引用&#xff08;universal reference&#xff09;引用折叠完美转发&#xff08;std::forward&#xff09; 万能引用/通用引用&#xff08;universal reference&#xff09; C11增加了右值的概念&#xff0c;在模板中&#xff0c;可以用&&来表示…