继承,super,重写,多态,抽象,接口
继承,super,重写,多态,抽象,接口
继承
extends
用于表示两个类之间的继承关系,继承是OOP的四大特性之一,他允许一个类(称之为子类或派送类) 继承另一个类(称之为父类或基类)的变量和方法,子类可以复用父类的方法和变量,也可以添加和覆盖父类的方法和变量
extends的基本语法
- 使用
extends
关键字来声明子类继承父类
class ParentClass()
{
//父类属性和方法
}
class ChildrenClass extends ParentClass()
{
//子类的属性与方法
}
- 上述ChildrenClass类继承了ParentClass类,子类可以复用ParentsClass类的属性与方法
继承的特性
- 代码复用:子类可以之间使用父类的方法和属性,无需重新编写
- 扩展性:子类可以添加新的属性和方法,以满足实际开发需求
- 多态性:通过继承子类可以覆盖父类的方法,实现多态性
继承的限制
- java中不支持多继承,即一个类只能有一个父类.但后续学的接口是可以多继承的.
- 再java中所有类都直接或间接的继承Object类
继承的层级结构
- 由于继承的限制性,即一个子类只能继承一个父类,但一个父类可以被多个子类继承,子类也可以作为其他子类的父类.再java中就形成了一个树状层级结构,
继承下构造器的调用
- 在创建子类时,java会优先调用父类的构造器(如果没有显式调用,则会调用无参构造器),然后再调用子类的构造器,.如果需要显式调用,则需用
super
关键字来实现
class ParentClass
{
public ParentClass()
{
System.out.println("这是父类的无参构造方法");
}
public ParentClass(String str)
{
System.out.println("这是父类的一个带参构造器");
}
}
class ChildrenClass extends ParentClass{
public ChildrenClass()
{
System.out.println("这是子类的无参构造方法");
}
public ChildrenClass(String str){
System.out.println("这是一个子类的带参构造器");
}
public static void main(String[] args) {
ChildrenClass childrendclass = new ChildrenClass();
ChildrenClass childrenclass new ChildrenClass("11");
}
}
- 分析:
ChildrenClass
继承了ParentClass
接着再main函数创建ChildrenClass
的无参实例对象时,会先调用父类的无参构造器打印这是父类的无参构造方法
,接着再调用子类的无参构造器这是子类的无参构造方法
当实例化子类带参构造器时,也会先调用父类的带参构造器这是父类的无参构造方法
,接着调用子类的带参构造器这是一个子类的带参构造器
- 当子类构造器调用了父类的有参方法,则父类的无参构造器不会被调用,只会调用有参构造器
调用了无参构造器构造器,则父类的有参构造器不会被调用, 即每次只会调用一种构造器
super关键字
super
关键字是java中重要的一个引用变量,他主要用于引用当前对象的父类对象,super()
实际是调用父类的构造器
调用父类构造函数
- 在子类的构造器中,你可以使用
super()
调用父类的构造函数,
访问父类中的成员变量
- 若子类想要调用父类的成员变量时可以用
super
关键字进行调用
class Parent {
int value = 100;
}
class Child extends Parent {
int value = 200;
void display() {
System.out.println("Parent value: " + super.value); //调用父类的value
System.out.println("Child value: " + this.value);
}
}
public class Main {
public static void main(String[] args) {
Child child = new Child();
child.display();
}
}
访问父类的方法
在子类中可以使用super关键字子访问父类的方法
class Parent {
void display() {
System.out.println("Parent display method");
}
}
class Child extends Parent {
@Override
void display() {
super.display(); // 调用父类的display方法
System.out.println("Child display method");
}
}
public class Main {
public static void main(String[] args) {
Child child = new Child();
child.display();
}
}
重写(Override
override:也称覆盖,重写是子类对父类非静态,非private,非final方法的实现过程进行重新编写, 返回值(JDK7之后,被重写的方法返回值,类型可以不同,但必须有父子关系)和形参都不能改变.即外壳不能改变→重写的核心
方法名与参数列表必须相同
子类中的重写方法必须与父类中的被重写方法具有相同的方法名和参数列表,相同的参数列表即意味着,参数类型,数量,顺序都必须相同
返回类型
- 如果父类被重写的方法放回的是基本数据类型或
void
,则子类重写的方法的返回值必须与父类方法一直 - 如果父类被重写方法放回的是引用数据类型,则子类重写的方法返回值的类型可以与父类相同或者是其子类型
public class Animal {
// ... 其他方法 ...
public Animal getAnimal() {
return new Animal(); // 返回一个Animal对象
}
}
public class Dog extends Animal {
// ... 其他方法 ...
// 重写getAnimal方法,但返回更具体的类型Dog
@Override
public Dog getAnimal() {
return new Dog(); // 返回一个Dog对象,它是Animal的子类 也是合法的
}
}
访问权限(封装
- 子类重写方法的权限(
public,protected,默认,private
)都不能低于父类方法的访问权限,例如父类中方法是public
,则子类中必须是public
异常处理
- 子类重写方法抛出的异常类型,应该是父类被重写方法抛出的异常的子集或者相同,即子类不能抛出比父类多的异常
静态方法不能被重写
- 静态方法只与类相关,并非与实例相关,.静态方法不属于继承的层次结构.
final方法不能被重写
被final
修饰的方法表示该方法不能被覆盖或继承,因此子类不能重写父类中的final
方法
多态
严格的文字定义:它允许我们使用父类类型变量来引用子类对象这意味着,当我们对父类类型的变量进行操作时,具体的行为取决于该变量所引用的实际对象的类型
简单的理解:同一个行为具有不同的表现形式,即执行一段代码java在运行中能根据对象产生不同的结果
多态的前提条件
- 子类继承同一父类
- 子类覆盖(重写)父类方法
- 父类引用指向子类对象
- 注意点:多态下,引用调用的方法是子类重写方法,调用的属性是父类的属性
抽象类 (abstract
抽象类也是类,只是具备了一些特殊的性质;抽象类的主要作用是提供了一个模板或是框架,这个模板中定义了一些属性与方法,但是并不需要完全实现这些方法.→相当于你告诉其他类:你们可以按照我的这个模板来创建自己的类,但是你需要实现我未完成的部分;
模板作用
- 想象你有一个抽象类叫做
Animal
,它有一个方法eat()
。但不同的动物吃东西的方式可能不同,所以eat()
方法没有具体的实现。其他类,比如Dog
和Cat
,可以继承Animal
类,然后各自实现自己的eat()
方法.
强制子类实现某个方法
- 如果你有一个抽象方法(即在抽象类中声明但没有实现的方法),那么任何继承这个抽象类的子类都必须实现这个方法。这确保了子类具有某种特定的功能或行为
代码复用
- 抽象类可以包含一些通用的、非抽象的方法和属性,这些方法和属性可以被所有子类共享,避免了在每个子类中重复编写相同的代码
定义了接口
- 虽然接口(Interface)也用于定义类的行为,但抽象类可以包含方法的实现,而接口只能定义方法签名。因此,在某些情况下,抽象类可以提供更灵活的接口定义。
注意点
- 抽象类不能被实例化
- 这是
abstract
类最基本的特点。由于抽象类可能包含没有具体实现的抽象方法,因此不能创建抽象类的实例。只能创建抽象类的非抽象子类的实例
- 抽象类中可以包含抽象方法和非抽象方法
- 有抽象方法的类一定是抽象类,但抽象类不一定有抽象方法。即使抽象类中可以没有抽象方法,普通类中不能有抽象方法
- 子类必须实现父类中的所有抽象方法
- 如果一个类继承了抽象类,并且该抽象类中有抽象方法,那么子类必须提供这些方法的具体实现,除非子类也是抽象类
- 抽象方法不能有方法体
- 被
abstract
修饰的方法不能有具体的方法体,即没有大括号{}
和具体的实现代码
- 不能与
private
、static
、final
等关键字共用
private
修饰的方法表示私有,不允许子类访问,而abstract
修饰的方法必须被子类覆盖重写才能使用,所以二者矛盾。static
关键字修饰的是静态方法,静态方法属于类而不属于实例→属于类,而抽象方法没有具体的实现,需要子类来提供,所以抽象方法不能是静态的。final
关键字表示最终的,不可改变的,而抽象方法需要子类来实现,所以不能是final
的。
- 抽象类必须有构造方法
- 虽然抽象类不能被实例化,但它的构造方法可以用于被子类调用。子类在创建对象时,会先调用父类的构造方法
// 抽象类 Animal
abstract class Animal {
// 抽象方法
abstract void makeSound();
// 非抽象方法
void eat() {
System.out.println("The animal eats.");
}
// 构造方法
Animal() {
System.out.println("Animal is being constructed.");
}
}
// Dog 类继承自 Animal
class Dog extends Animal {
// 实现从 Animal 继承的抽象方法
@Override
void makeSound() {
System.out.println("The dog barks.");
}
// Dog 类的构造方法
Dog() {
super(); // 调用父类的构造方法
System.out.println("Dog is being constructed.");
}
}
// 主类
public class Main {
public static void main(String[] args) {
// 抽象类不能被实例化
// Animal animal = new Animal(); // 这是错误的
// 创建 Dog 和 Cat 的对象
Dog dog = new Dog();
Cat cat = new Cat();
// 调用方法
dog.eat();
dog.makeSound();
}
}
- 结果如下
Animal is being constructed. //父类无参构造器先被调用
Dog is being constructed.
The animal eats.
The dog barks.
接口
接口声明了一组方法(规范),但不关心这些方法(规范)是怎么实现的,任何实现这些接口的类都必须遵循这些方法(规范),但对于具体方法的细节完全由类自身决定.
接口可以看作是一种特殊的类,但接口中所有的方法都是抽象方法(即没有方法体),通常不会写属性;所有的属性都是常量(即使用
public static final
修饰
接口的特性
1.抽象性
- 接口中的所有方法都是抽象的,或者说都被隐型定义成abstract;的因此它们没有方法体。实现接口的类必须为接口中的所有方法提供具体的实现
2.接口不能被实例化
- 接口本身不能被实例化,即不能使用
new
关键字来创建接口的实例。但是,可以声明接口的引用变量,该变量引用实现该接口的类的实例。
3.接口可以多实现
- 一个类可以实现多个接口,通过逗号分隔接口名。这允许类继承多个接口中的方法规范
public class Dog implements Animal, Runnable { //多实现接口
@Override
public void eat() {
System.out.println("Dog is eating");
}
@Override
public void sleep() {
System.out.println("Dog is sleeping");
}
@Override
public void run() {
System.out.println("Dog is running");
}
}
4.多继承的替代
- 在Java中,类只能继承自一个父类,但可以实现多个接口。这提供了一种替代多重继承的方式,允许类继承多个行为。
5.接口的继承
- 接口可以继承自其他接口,通过
extends
关键字实现。这允许接口之间共享方法的规范
// 定义一个父接口
interface ParentInterface {
void method1();
void method2();
int CONSTANT = 10; // 可以在接口中定义常量
}
// 定义一个子接口,继承自ParentInterface
interface ChildInterface extends ParentInterface {
void method3();
}
- 在这个例子中,
ChildInterface
继承自ParentInterface
,因此它自动包含了ParentInterface
中定义的所有方法(method1()
和method2()
)和常量(CONSTANT
)。同时,ChildInterface
还可以定义自己特有的方法(如method3()
)。
接口的作用
- 多继承
- 不同子类实现相同的行为
JDK1.8之后(包括1.8)接口的变化
- 可以在接口写非抽象方法
// 使用接口名.方法名调用
static void 方法名称() {
}
// 可以被子类继承,实例化子类之后调用
default void 方法名称() {
}
接口与抽象类的区别
实现与继承
- 接口:一个类可以实现多个接口,通过
implements
关键字实现,接口中所有的方法都是抽象的,即没有方法体 - 抽象类: 一个类只能继承一个抽象类,沟通
extends
关键字实现,抽象类中可以包含抽象方法和非抽象方法
使用场景
- 接口: 通常用于定义一种规范或契约,不关心对象的具体实现.如定义API,插件架构等
- 抽象类: 常用于提供一个公共父类,包含一些公共的方法和属性,有子类继承并实现具体的方法.
设计原则
- 接口:强调“契约”和“规范”,关注对象的行为。一个类可以实现多个接口,从而具备多种能力
- 抽象类:强调模板与复用,通过继承实现代码的复用,子类继承抽象类后,可以直接使用父类中的非抽象方法和属性。
实例化
- 接口:接口不能被实例化,只能被实现
- 抽象类:可以被实例化,但只能通过子类被实例化,如果抽象方法中包括非抽象方法则子类可以直接调用.
继承,super,重写,多态,抽象,接口的更多相关文章
- java面向对象3-继承(继承、抽象类、抽象接口)
4.继承 面向对象概念-类与对象的关系 封装:指隐藏对象的属性和实现细节,仅对外提供公共访问方式,private-构造方法/构造器-this关键字-static关键字(javadoc制作工具类) -代 ...
- JAVA 之 多态 抽象 接口
一:多态 1:多态 一个对象有多种形式的能力 2:步骤 1编写父类派生子类 2子类重写父类方法 3用父类的数据类型引用子类对象 3:静态多态的实现方式就是方法重载 4:动态多态的实现方式就是重写 ...
- Three---面向对象与面向过程/属性和变量/关于self/一些魔法方法的使用/继承/super方法/多态
python的面向对象 面向对象与面向过程 面向过程 面向过程思想:需要实现一个功能的时候,看重的是开发的步骤和过程,每一个步骤都需要自己亲力亲为,需要自己编写代码(自己来做) 面向对象 面向对象的三 ...
- 继承(extends), 多态 , 抽象(abstract)接口() 易混难点解析
特性 java是单继承的,一个类直接继承的父类只能有唯一的一个 java中父类可以有多个子类 Object是所有类的父类,一个类没有父类则默认继承Object; 继承中的重写 子类重写方法访问权限不能 ...
- Java中关于继承、类、多态、接口的知识点
继承 含义:在面向对象编程中,可以通过扩展一个已有的类,并继承该类的属性和行为,来创建一个新的类 优点:1)代码的重用性:2)子类扩展父类的属性和方法:3)父类的属性和方法可用于子类:4)设计应用程序 ...
- java四大特性理解(封装继承多态抽象)
封装: 封装是把过程和数据包围起来,对数据的访问只能通过已定义的接口.面向对象计算始于这个基本概念,即现实世界可以被描绘成一系列完全自治.封装的对象,这些对象通过一个受保护的接口访问其他对象.封装是一 ...
- Java开发知识之Java的继承多态跟接口*
Java开发知识之Java的继承多态跟接口 一丶继承 1.继承的写法 在Java中继承的 关键字是 extends 代表一个类继承另一个类. 继承的含义以及作用: 继承就是基于某个父类的扩展.制定出来 ...
- Java知识回顾 (7) 继承、多态与接口、封装
一.继承 1.1 继承的特性 子类拥有父类非 private 的属性.方法. 子类可以拥有自己的属性和方法,即子类可以对父类进行扩展. 子类可以用自己的方式实现父类的方法. Java 的继承是单继承, ...
- PythonI/O进阶学习笔记_3.2面向对象编程_python的继承(多继承/super/MRO/抽象基类/mixin模式)
前言: 本篇相关内容分为3篇多态.继承.封装,这篇为第二篇 继承. 本篇内容围绕 python基础教程这段: 在面向对象编程中,术语对象大致意味着一系列数据(属性)以及一套访问和操作这些数据的方法.使 ...
- java中封装,继承,多态,接口学习总结
### 一:封装java中封装是指一种将抽象性函式接口的实现细节部分包装.隐藏起来的方法. 封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问.要访问该类的代码和数据,必须通 ...
随机推荐
- 重新整理.net core 计1400篇[七] (.net core 中的依赖注入)
前言 请阅读第六篇,对于理解.net core 中的依赖注入很关键. 和我们上一篇不同的是,.net core服务注入保存在IServiceCollection 中,而将集合创建的依赖注入容器体现为I ...
- Kafka 线上性能调优
Kafka 线上性能调优是一项综合工程,不仅仅是 Kafka 本身,还应该从硬件(存储.网络.CPU)以及操作系统方面来整体考量,首先我们要有一套生产部署方案,基于这套方案再进行调优,这样就有了可靠的 ...
- 【2021.6.26 NOI模拟】Problem B. 简单题 another solution
Problem Description Input 从文件 b.in 中读入数据. 一个正整数 n. Output 输出到文件 b.out 中. 一个整数表示答案. Sample Data Input ...
- 力扣697(java)-数组的度(简单)
题目: 给定一个非空且只包含非负数的整数数组 nums,数组的 度 的定义是指数组里任一元素出现频数的最大值. 你的任务是在 nums 中找到与 nums 拥有相同大小的度的最短连续子数组,返回其长度 ...
- 智能logo免费体验|如何让餐饮logo在点评网站上一眼出众?
简介:一个新的餐饮店铺,还没有人知晓,Logo就是这个重要的"门面",所传递的信息让人快速识别,就能产生记忆点,愿意进一步了解,从而为店铺带来流量和收益.如何让你的餐饮店铺log ...
- 可观测告警运维系统调研——SLS告警与多款方案对比
简介: 本文介绍对比多款告警监控运维平台方案,覆盖阿里云SLS.Azure.AWS.自建系统(ELK.Prometheus.TICK)等方案. 前言 本篇是SLS新版告警系列宣传与培训的第三篇,后续我 ...
- OpenYurt 联手 eKuiper,解决 IoT 场景下边缘流数据处理难题
简介: 云计算的出现促使物联网实现爆炸式增长.在设备规模和业务复杂度不断攀升的趋势之下,边缘计算因其能够将计算能力更靠近网络边缘和设备,从而带来云性能成本的降低,也在这波浪潮之下得到快速发展. 作者 ...
- [FAQ] docker-compose MySQL8 ERROR: Different lower_case_table_names settings for server
MySQL8 启动时 lower_case_table_names 的设置和初始值不一致时,会报 ERROR. 在 docker-compose 中,只需要在命令中加入命令选项即可,并配置一个新的 v ...
- WPF 通过 Windows Template Studio 快速搭建项目框架和上手项目
本文对新手友好.在咱开始一个新项目的时候,可以利用 Windows Template Studio 快速搭建整个项目的框架.搭建出来的框架比较现代化,适合想要快速开发一个项目的大佬使用,也适合小白入门 ...
- 2019-11-29-C#-如何写-DEBUG-输出
title author date CreateTime categories C# 如何写 DEBUG 输出 lindexi 2019-11-29 08:28:35 +0800 2018-2-13 ...