OOP 设计模式:接口与类的封装和重写(override)以及重载(overload)

2024-03-25 06:58

本文主要是介绍OOP 设计模式:接口与类的封装和重写(override)以及重载(overload),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

要点

  • 子类是 extends 父类出来的

  • 子类会集成父类所有 public 类型的实例变量和方法,但不会集成父类所有 private 类型的变量和方法

  • 继承下来的属性可以被覆盖掉,但实例变量不能被覆盖掉

  • 类的多态性可以从方法override 和 overload 来体现

  • 一个类可以继承另外一个类或者实现多个接口


 

重写 Override

工程意义:重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变,核心重写!

如果需要扩展行为,就可以通过子类来实现,因此,继承是给类扩展和添加行为时的唯一工具。从继承开始说起。

type Rect = {x: number,y: number
}class Animal {protected flegCount:number;protected isAlive:boolean;protected color:string;protected position: Rect;constructor(){this.flegCount = 4;this.isAlive = true;this.color = "white"this.position = {x: 0,y: 0}}speak():string|null {return null;}
}class Dog extends Animal {speak():string|null {return "旺旺旺!";}
}class Cat extends Animal {speak():string|null {return "喵喵喵!";}
}

发生重写 Override - Animal 类 和 Cat 类中的 speak 方法的方法名和参数都一样

上面的 TypeScript 代码片段是一个基础的继承示例。Dog 和 Cat 类继承自 Animal,这意味着它们拥有 Animal 所有的属性和方法,我们不需要重新去定义它们,除非我们想覆盖原来的实现,就像上面的例子一样。继承允许我们将公共行为、状态(方法和属性)抽象到一个单独的地方,我们可以从那里(父类)提取。

const d1 = new Dog();
const c1 = new Cat();console.log(d1.speak());
console.log(c1.speak());

在线地址

继承的另一大好处是用父类的类型声明的变量也可以兼容来自子类的对象,主要体现在 Java,TypeScript 等强类型语言。比如:

let animals:Animal[] = [new Cat(), new Dog()]
animals.forEach( a => console.log(a.speak()));

在线地址

紧接着之前定义的类,这个例子声明了一组 Animal 类型的元素,包含了一个 Cat 和 一个 Dog。这是可行的,因为两个对象有相同的父类。同样,我们可以在安全地调用 speak 方法。因为这个方法已经在父类中定义了,我们知道所有的对象都有它。

重载 Overload

工程意义: 重载允许一个函数接受不同数量或类型的参数时,作出不同的处理

因为重载方法不是用来满足定义在父类(发生继承场景)的多态,所以重载的方法比较有扩展性。

class Overloads {uniqueID: number | string | null;constructor() {this.uniqueID = null;}addNums(a: string, b: string);addNums(a: number, b: number);addNums(a: string, b: number);addNums(a: number, b: string);addNums(a: number|string, b: number| string): number {if (typeof a === 'string') {a = Number(a);} if (typeof b === 'string') {b = Number(b);} return a + b;}setUniqueID(theID: string);setUniqueID(ssNumber: number) setUniqueID(value: number|string) {if (typeof value === 'number') {this.uniqueID = value} else if (typeof value === 'string') {const numberString = value + "";this.uniqueID = value}}}

发生重载 Overload - Overloads的同一个类中的多个 addNums 方法名相同,参数不同

执行测试

const o = new Overloads();
console.log('------- example1 ------')
console.log(o.addNums(1, 2));
console.log(o.addNums('3','5'));console.log('------- example2 ------')
console.log(o.setUniqueID('1'));
console.log(o.uniqueID)console.log(o.setUniqueID(2));
console.log(o.uniqueID)

在线地址

在 Java 中是这样子的

public class Overloads {String uniqueID;public int addNums(int a, int b) {return a + b;}public double addNums(double a, double b) {return a + b;}public void setUniqueID(String theID) {uniqueID = theID}public void setUniqueID(int ssNumber) {String numString = "" + ssNumber;setUniqueID(numString)}
}


 

重写与重载的区别

区别点

重载Overload方法

重写Overwrite方法

参数列表

必须修改

一定不能修改

返回类型

可以修改

一定不能修改

访问权限

可以修改

一定不能做更严格的限制

(可以降低限制,比如 protected 修改 public)


方法的重写(Overriding)和重载(Overloading)是面向对象中多态性的不同表现,重写是父类与子类之间多态性的一种表现,重载可以理解成多态的具体表现形式。

  • (1)方法重载是一个类中定义了多个方法名相同,而他们的参数的数量不同或数量相同而类型和次序不同,则称为方法的重载(Overloading)。

  • (2)方法重写是在子类存在方法与父类的方法的名字相同,而且参数的个数与类型一样,返回值也一样的方法,就称为重写(Overriding)。

  • (3)方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现。

更严厉的权限描述

type Rect = {x: number,y: number
}class Animal {protected flegCount:number;protected isAlive:boolean;protected color:string;protected position: Rect;constructor(){this.flegCount = 4;this.isAlive = true;this.color = "white"this.position = {x: 0,y: 0}}public speak():string|null {return null;}
}class Dog extends Animal {speak():string|null {return "旺旺旺!";}
}class PrivateDog extends Animal {//Class 'PrivateDog' incorrectly extends base class 'Animal'.//Property 'speak' is protected in type 'PrivateDog' but public in type 'Animal'.protected speak():string|null {return "严厉的旺旺旺!";}
}const d = new Dog();
console.log(d.speak())

在线地址

抽象类 Abstract Class

工程意义:因为抽象类不能实例化对象,所以必须要有子类来实现它之后才能使用。这样就可以把一些具有相同属性和方法的组件进行抽象,这样更有利于代码和程序的维护

abstract class Department {constructor(public name: string) {}printName(): void {console.log('Department name: ' + this.name);}abstract printMeeting(): void; // 必须在派生类中实现
}class AccountingDepartment extends Department {constructor() {super('Accounting and Auditing'); // 在派生类的构造函数中必须调用 super()}printMeeting(): void {console.log('The Accounting Department meets each Monday at 10am.');}generateReports(): void {console.log('Generating accounting reports...');}
}let department: Department; // 允许创建一个对抽象类型的引用
department = new Department(); // 错误: 不能创建一个抽象类的实例
department = new AccountingDepartment(); // 允许对一个抽象子类进行实例化和赋值
department.printName();
department.printMeeting();
department.generateReports(); // 错误: 方法在声明的抽象类中不存在

在线地址

什么时候用类或者接口

  1. 抽象类适合用来定义某个领域的固有属性,也就是本质,接口适合用来定义某个领域的扩展功能。

  2. 当需要为一些类提供公共的实现代码时,应优先考虑抽象类。因为抽象类中的非抽象方法可以被子类继承下来,使实现功能的代码更简单。

  3. 当注重代码的扩展性跟可维护性时,应当优先采用接口。

    1. ①接口与实现它的类之间可以不存在任何层次关系,接口可以实现毫不相关类的相同行为,比抽象类的使用更加方便灵活;

    2. ②接口只关心对象之间的交互的方法,而不关心对象所对应的具体类。接口是程序之间的一个协议,比抽象类的使用更安全、清晰。一般使用接口的情况更多。

案例1 接口:植物园内的水果,可以被拆下来,并且未来可以做成果汁

  

案例2 抽象类:狗狗可以有很多品种

 

 

案例3 接口:交通工具

 

案例4 抽象类:企业雇佣的员工分类(小时工,周薪员工等员工)

 

附录

  • 《Head First Java》 Head first java chapter 7 继承与多态_dengmu1918的博客-CSDN博客

  • 接口与抽象类的区别 深入理解Java的接口和抽象类 - Matrix海子 - 博客园

  • 何时使用接口(抽象类)? - dashuai的博客 - 博客园

这篇关于OOP 设计模式:接口与类的封装和重写(override)以及重载(overload)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/844181

相关文章

SpringBoot实现不同接口指定上传文件大小的具体步骤

《SpringBoot实现不同接口指定上传文件大小的具体步骤》:本文主要介绍在SpringBoot中通过自定义注解、AOP拦截和配置文件实现不同接口上传文件大小限制的方法,强调需设置全局阈值远大于... 目录一  springboot实现不同接口指定文件大小1.1 思路说明1.2 工程启动说明二 具体实施2

Python用Flask封装API及调用详解

《Python用Flask封装API及调用详解》本文介绍Flask的优势(轻量、灵活、易扩展),对比GET/POST表单/JSON请求方式,涵盖错误处理、开发建议及生产环境部署注意事项... 目录一、Flask的优势一、基础设置二、GET请求方式服务端代码客户端调用三、POST表单方式服务端代码客户端调用四

Spring Security重写AuthenticationManager实现账号密码登录或者手机号码登录

《SpringSecurity重写AuthenticationManager实现账号密码登录或者手机号码登录》本文主要介绍了SpringSecurity重写AuthenticationManage... 目录一、创建自定义认证提供者CustomAuthenticationProvider二、创建认证业务Us

基于Redisson实现分布式系统下的接口限流

《基于Redisson实现分布式系统下的接口限流》在高并发场景下,接口限流是保障系统稳定性的重要手段,本文将介绍利用Redisson结合Redis实现分布式环境下的接口限流,具有一定的参考价值,感兴趣... 目录分布式限流的核心挑战基于 Redisson 的分布式限流设计思路实现步骤引入依赖定义限流注解实现

SpringBoot实现RSA+AES自动接口解密的实战指南

《SpringBoot实现RSA+AES自动接口解密的实战指南》在当今数据泄露频发的网络环境中,接口安全已成为开发者不可忽视的核心议题,RSA+AES混合加密方案因其安全性高、性能优越而被广泛采用,本... 目录一、项目依赖与环境准备1.1 Maven依赖配置1.2 密钥生成与配置二、加密工具类实现2.1

使用Python的requests库调用API接口的详细步骤

《使用Python的requests库调用API接口的详细步骤》使用Python的requests库调用API接口是开发中最常用的方式之一,它简化了HTTP请求的处理流程,以下是详细步骤和实战示例,涵... 目录一、准备工作:安装 requests 库二、基本调用流程(以 RESTful API 为例)1.

JAVA覆盖和重写的区别及说明

《JAVA覆盖和重写的区别及说明》非静态方法的覆盖即重写,具有多态性;静态方法无法被覆盖,但可被重写(仅通过类名调用),二者区别在于绑定时机与引用类型关联性... 目录Java覆盖和重写的区别经常听到两种话认真读完上面两份代码JAVA覆盖和重写的区别经常听到两种话1.覆盖=重写。2.静态方法可andro

Java 方法重载Overload常见误区及注意事项

《Java方法重载Overload常见误区及注意事项》Java方法重载允许同一类中同名方法通过参数类型、数量、顺序差异实现功能扩展,提升代码灵活性,核心条件为参数列表不同,不涉及返回类型、访问修饰符... 目录Java 方法重载(Overload)详解一、方法重载的核心条件二、构成方法重载的具体情况三、不构

Java设计模式---迭代器模式(Iterator)解读

《Java设计模式---迭代器模式(Iterator)解读》:本文主要介绍Java设计模式---迭代器模式(Iterator),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录1、迭代器(Iterator)1.1、结构1.2、常用方法1.3、本质1、解耦集合与遍历逻辑2、统一

Golang如何对cron进行二次封装实现指定时间执行定时任务

《Golang如何对cron进行二次封装实现指定时间执行定时任务》:本文主要介绍Golang如何对cron进行二次封装实现指定时间执行定时任务问题,具有很好的参考价值,希望对大家有所帮助,如有错误... 目录背景cron库下载代码示例【1】结构体定义【2】定时任务开启【3】使用示例【4】控制台输出总结背景