一. 什么是接口
接口在我们现实生活中处处可见,比如手机充电器的接口,usb接口等。我们今天学习的这个接口跟我们生活中的接口有什么区别呢?
接口关键字:interface :规定类必须具有的功能
interface A{
//接口没有构造函数
num1:number
//接口中的方法不能有方法体,必须写上返回值类型
a1():void
}
//接口不能被实例化
//let a:A=new A() //报错
1.1 接口的总结:
1.接口没有构造函数
2.接口中的方法不能有方法体,必须写上返回值类型
3.接口不能被实例化
1.2 实现类
实现类的概念: 必须有接口中的属性,必须重写接口中的方法
使用接口需要使用implements关键字
implements:实现接口
//实现小电风扇插入USB接口,可以调节风扇速度,拔出usb接口则停止工作
//创建Usb接口
interface Usb{
in():void;
outs():void;
}
// implements 实现接口
class Fs implements Usb{
type:string
ts(){
console.log('调节风扇速度');
}
constructor(type:string){
this.type=type
}
in():void{
console.log('风扇插入usb');
}
outs():void{
console.log('风扇拔出usb');
}
}
子类只能继承一个父类,但是可以有多个接口,我们做个小练习
组装成一个电脑
计算机有品牌 型号属性
cpu 有cpu的品牌,主频 ,介绍
硬盘 有容量 介绍
内存 有 容量 介绍
//创建了一个电脑类 有品牌 型号属性
class Comp{
brand:string
type:string
constructor(brand:string,type:string){
this.brand=brand
this.type=type
}
info(){
console.log(`${this.brand}电脑品牌:${this.type}型号`);
}
}
//创建了一个CPU的接口
interface Cpu{
cpu(brand:string,zp:string):void
}
//创建了一个硬盘的接口
interface Yp{
yp(rl:string):void
}
//创建了一个内存的接口
interface Nc{
nc(rl:string):void
}
//我们开始组装我们的电脑 继承了电脑的类,连接了CPU,硬盘,内存的接口
class Cp extends Comp implements Cpu,Yp,Nc{
constructor(brand:string,type:string){
super(brand,type)
}
cpu(brand:string,zp:string):void{
console.log(`CPU的品牌是:${brand},主频是:${zp}`);
}
yp(rl: string): void {
console.log(`硬盘的容量是:${rl}`);
}
nc(rl: string): void {
console.log(`内存容量是:${rl}`);
}
}
//实例化对象
let c1:Cp=new Cp('联想','小星')
c1.info()
c1.cpu('Inter','3.8GHz')
c1.yp('3000GB')
c1.nc('4GB')
运行结果:
二. 多态的实例
2.1.功能介绍
今天我们制作的是影音管理系统,实现功能有:把数据添加到页面中,添加音频或视频 删除存入的数据,接下来让我们一起看一下如何实现的
2.2需要准备的数据
在ets文件夹中创建一个model文件夹,在model文件夹中放入我们所写的TS代码,并导出出来,方便我们后续引用。
我们需要一个Videos.ts(视频)文件 ,Audio.ts(音频文件),Medias(媒体文件)
medias文件是 视频和音频文件的共同属性,里面有name(名称)属性, size(大小)属性,
show(介绍)属性,times(时长)属性
我们需要把我们所需的属性和方法都要封装 我们用标识符 Private 私有属性,只能 在本类中使用,我们还需要export关键字导出文件
//媒体
export class Medias{
private _name: string
public set name(value: string) {
this._name = value
}
public get name(): string {
return this._name
}
private _size: number
public set size(value: number) {
this._size = value
}
public get size(): number {
return this._size
}
private _show: string
public set show(value: string) {
this._show = value
}
public get show(): string {
return this._show
}
private _times: number
public set times(value: number) {
this._times = value
}
public get times(): number {
return this._times
}
constructor(name:string,size:number,show:string,times:number) {
this._name=name
this._size=size
this._show=show
this._times=times
}
}
,我们创建很多属性方法,还要封装,初始化,当设置私有属性还需要get和set,这是我们可以右键找到Generate,点击进去
显示这个页面,选择Getter and Setter就自动帮我们生成好代码了,节省了不少时间
Audio.ts类继承Medias类
// 音频: 名字 大小 简介 作曲 作词 原唱 翻唱 时长
import { Medias } from './Medias';
export class Audio extends Medias{
private _zq: string;
public set zq(value: string) {
this._zq = value;
}
public get zq(): string {
return this._zq;
}
private _zc: string;
public set zc(value: string) {
this._zc = value;
}
public get zc(): string {
return this._zc;
}
private _yc: string;
public set yc(value: string) {
this._yc = value;
}
public get yc(): string {
return this._yc;
}
constructor(name: string, size: number, show: string, times: number, zq: string, zc: string, yc: string, fc: string) {
super(name, size, show, times);
this._zq = zq;
this._zc = zc;
this._yc = yc;
this._fc = fc;
}
private _fc: string;
public set fc(value: string) {
this._fc = value;
}
public get fc(): string {
return this._fc;
}
}
Videos.ts类继承Medias类
// 视频: 名字 大小 简介 时长 类型 主演 画质 导演 制片人
import { Medias } from './Medias';
export class Videos extends Medias{
private _type: string;
public set type(value: string) {
this._type = value;
}
public get type(): string {
return this._type;
}
private _zy: string;
public set zy(value: string) {
this._zy = value;
}
public get zy(): string {
return this._zy;
}
private _hz: string;
public set hz(value: string) {
this._hz = value;
}
public get hz(): string {
return this._hz;
}
private _dy: string;
public set dy(value: string) {
this._dy = value;
}
public get dy(): string {
return this._dy;
}
private _zpr: string;
public set zpr(value: string) {
this._zpr = value;
}
public get zpr(): string {
return this._zpr;
}
constructor(name: string, size: number, show: string, times: number, type: string, zy: string, hz: string, dy: string,
zpr: string) {
super(name, size, show, times);
this._type = type;
this._zy = zy;
this._hz = hz;
this._dy = dy;
this._zpr = zpr;
}
}
2.3主程序
我们创建了一个medias数组用于存储我们数据,md实例化Medias isAorV是判断当前是音频还是视频后续会介绍到 ad,vd是音频和视频的实例化
aboutToAppear:生命周期,即打开页面就运行里面代码
ps:声明数据内容没有任何意义,仅作为练习,如入侵犯,请私信,我们也会第一时间改之
@State message: string = '影音管理系统';
@State medias:Medias[]=[]
@State md:Medias=new Medias('',0,'',0)
@State isAorV:boolean=false //默认是音频
@State ad:Audio=new Audio('',0,'',0,'','','','')
@State vd:Videos=new Videos('',0,'',0,'','','','','')
aboutToAppear(): void {
this.medias.push(new Videos('泰坦尼克号',2048,'一段凄美的爱情故事',120,'爱情','莱昂纳多','4k','莱昂纳多','莱昂纳多'))
this.medias.push(new Audio('只因你太美',100,'鸡和篮球',5,'瑶','蔡坤','坤坤','蔡徐坤'))
this.medias.push(new Videos('西游记',1200,'四个男人和一堆妖怪的取经之路',90,'科幻','六小龄童','2k','杨杰','莱昂纳多'))
this.medias.push(new Videos('蜘蛛侠',3000,'被蜘蛛咬了一口',140,'科幻','蜘蛛','4k','莱昂纳多','莱昂纳多'))
this.medias.push(new Audio('传奇',200,'没听过不知道',6,'王菲','冰冰','坤坤','花花'))
this.medias.push(new Audio('青花瓷',300,'一个瓷器',4,'方文山','闪闪','坤坤','草草'))
this.medias.push(new Videos('乡村爱情故事',4048,'四个老头打架',220,'爱情','刘能','高清','赵本山','赵本山'))
this.medias.push(new Videos('猪猪侠',4077,'一只猪的故事',300,'动画','猪猪侠','1080','海燕','莱昂纳多'))
this.medias.push(new Audio('张三的歌',200,'法外狂徒',3,'民法典','蔡坤','坤坤','绿绿'))
this.medias.push(new Videos('喜人奇妙夜',20480,'喜剧',4800,'喜剧','洋洋','4k','莱昂纳多','莱昂纳多'))
this.medias.push(new Audio('泡沫',300,'悲伤的音乐',3,'邓紫棋','邓紫棋','邓紫棋','邓紫棋'))
this.medias.push(new Videos('明日之星',100,'综艺',60,'综艺','明星','4k','莱昂纳多','莱昂纳多'))
this.medias.push(new Audio('江南',300,'style',4,'陈博','蔡坤','博博','红红'))
}
循环数组中数据
在ListItem中添加swipeAction组件实现删除功能,前提需要自定义删除组件
@Builder DelButton(index:number){
Button('删除')
.type(ButtonType.Normal)
.width('20%')
.height(150)
.onClick(() => {
this.medias.splice(index,1)
})
}
Column(){
Text(this.message).fontSize(30)
List({space:10}){
ForEach(this.medias,(md:Medias,index)=>{
ListItem(){
if(md instanceof Audio){ //音频
Column(){
Row(){
// 音频: 名字 大小 简介 时长 作曲 作词 原唱 翻唱
Text(`歌名:${md.name}`)
Text(`大小:${md.size}`)
Text(`时长:${md.times}`)
}.width('100%').height(50).justifyContent(FlexAlign.SpaceBetween)
Row(){
Text(`作词:${md.zq}`)
Text(`作词:${md.zc}`)
Text(`原唱:${md.yc}`)
Text(`翻唱:${md.fc}`)
}.width('100%').height(50).justifyContent(FlexAlign.SpaceBetween)
Row(){
Text(`简介:${md.show}`)
}.width('100%').height(50).justifyContent(FlexAlign.SpaceBetween)
}.width('100%')
.backgroundColor('#ccc')
}else if(md instanceof Videos){ //视频
Column(){
Row(){
// 视频: 名字 大小 简介 时长 类型 主演 画质 导演 制片人
Text(`视频名:${md.name}`)
Text(`大小:${md.size}`)
Text(`时长:${md.times}`)
Text(`类型:${md.type}`)
}.width('100%').height(50).justifyContent(FlexAlign.SpaceBetween)
Row(){
Text(`导演:${md.dy}`)
Text(`主演:${md.zy}`)
Text(`画质:${md.hz}`)
Text(`制片人:${md.zpr}`)
}.width('100%').height(50).justifyContent(FlexAlign.SpaceBetween)
Row(){
Text(`简介:${md.show}`)
}.width('100%').height(50).justifyContent(FlexAlign.SpaceBetween)
}.width('100%')
.backgroundColor('#aaa')
}
}
.swipeAction({
end:this.DelButton(index)
})
})
}.height(400).width('90%')
结果展示:
实现输入添加效果
里面有非空判断,输入不能为空,留了个小bug,第一次输入值之后,清空后点击添加还是可以添加上去,有解决办法可以在评论区留言,看看大家都有什么好的办法来解决
Row(){
Button('音频')
.type(ButtonType.Normal).width('40%')
.onClick(() => this.isAorV=false)
Button('视频')
.type(ButtonType.Normal).width('40%')
.onClick(() => this.isAorV=true)
}.width('90%').justifyContent(FlexAlign.SpaceBetween).margin({top:10})
if(this.isAorV){ //视频
// 视频: 名字 大小 简介 时长 类型 主演 画质 导演 制片人
Column({space:5}){
Text('视频添加')
Row(){
TextInput({placeholder:'视频名称'}).borderRadius(0).width('30%')
.onChange(val=>this.vd.name=val)
TextInput({placeholder:'大小'}).borderRadius(0).width('30%')
.onChange(val=>this.vd.size=parseFloat(val))
TextInput({placeholder:'时长'}).borderRadius(0).width('30%')
.onChange(val=>this.vd.times=parseFloat(val))
}.width('100%').justifyContent(FlexAlign.SpaceBetween)
Row(){
TextInput({placeholder:'类型'}).borderRadius(0).width('30%')
.onChange(val=>this.vd.type=val)
TextInput({placeholder:'主演'}).borderRadius(0).width('30%')
.onChange(val=>this.vd.zy=val)
TextInput({placeholder:'制片人'}).borderRadius(0).width('30%')
.onChange(val=>this.vd.zpr=val)
}.width('100%').justifyContent(FlexAlign.SpaceBetween)
Row(){
TextInput({placeholder:'画质'}).borderRadius(0).width('30%')
.onChange(val=>this.vd.hz=val)
TextInput({placeholder:'导演'}).borderRadius(0).width('30%')
.onChange(val=>this.vd.dy=val)
TextInput({placeholder:'简介'}).borderRadius(0).width('30%')
.onChange(val=>this.vd.show=val)
}.width('100%').justifyContent(FlexAlign.SpaceBetween)
Button('添加').width('90%')
.onClick(()=>{
//非空验证
if(this.vd.name==''||this.vd.size==0||this.vd.hz==''||this.vd.type==''||this.vd.zy==''||this.vd.zpr==''||this.vd.show==''||this.vd.times==0||this.vd.dy==''){
promptAction.showToast({message:'不能为空'})
}else{
let b:Videos=this.vd
let vd1:Videos=new Videos(b.name,b.size,b.show,b.times,b.zy,b.hz,b.dy,b.zpr,b.type)
this.medias.push(vd1)
promptAction.showToast({message:'音频添加成功'})
}
})
}.width('90%')
}else{ //音频
// 音频: 名字 大小 简介 作曲 作词 原唱 翻唱 时长
Column({space:5}){
Text('音频添加')
Row(){
TextInput({placeholder:'音频名称'}).borderRadius(0).width('45%')
.onChange(val=>this.ad.name=val)
TextInput({placeholder:'大小'}).borderRadius(0).width('45%')
.onChange(val=>this.ad.size=parseFloat(val))
}.width('100%').justifyContent(FlexAlign.SpaceBetween)
Row(){
TextInput({placeholder:'时长'}).borderRadius(0).width('45%')
.onChange(val=>this.ad.times=parseFloat(val))
TextInput({placeholder:'作曲'}).borderRadius(0).width('45%')
.onChange(val=>this.ad.zq=val)
}.width('100%').justifyContent(FlexAlign.SpaceBetween)
Row(){
TextInput({placeholder:'作词'}).borderRadius(0).width('45%')
.onChange(val=>this.ad.zc=val)
TextInput({placeholder:'原唱'}).borderRadius(0).width('45%')
.onChange(val=>this.ad.yc=val)
}.width('100%').justifyContent(FlexAlign.SpaceBetween)
Row(){
TextInput({placeholder:'翻唱'}).borderRadius(0).width('45%')
.onChange(val=>this.ad.fc=val)
TextInput({placeholder:'简介'}).borderRadius(0).width('45%')
.onChange(val=>this.ad.show=val)
}.width('100%').justifyContent(FlexAlign.SpaceBetween)
Button('添加').width('90%')
.onClick(()=>{
//非空验证
if(this.ad.name==''||this.ad.size==0||this.ad.zq==''||this.ad.zc==''||this.ad.yc==''||this.ad.fc==''||this.ad.show==''||this.ad.times==0){
promptAction.showToast({message:'不能为空'})
}else{
let a:Audio=this.ad
let ad1:Audio=new Audio(a.name,a.size,a.show,a.times,a.zq,a.zc,a.yc,a.fc)
this.medias.push(ad1)
promptAction.showToast({message:'音频添加成功'})
}
})
}.width('90%')
运行结果 :


2.4主程序的完整代码
import { Medias } from '../model/Medias';
import { Videos } from '../model/Videos';
import { Audio } from '../model/Audio';
import { promptAction } from '@kit.ArkUI';
@Entry
@Component
struct MediaPage {
@State message: string = '影音管理系统';
@State medias:Medias[]=[]
@State md:Medias=new Medias('',0,'',0)
@State isAorV:boolean=false //默认是音频
@State ad:Audio=new Audio('',0,'',0,'','','','')
@State vd:Videos=new Videos('',0,'',0,'','','','','')
aboutToAppear(): void {
this.medias.push(new Videos('泰坦尼克号',2048,'一段凄美的爱情故事',120,'爱情','莱昂纳多','4k','莱昂纳多','莱昂纳多'))
this.medias.push(new Audio('只因你太美',100,'鸡和篮球',5,'瑶','蔡坤','坤坤','蔡徐坤'))
this.medias.push(new Videos('西游记',1200,'四个男人和一堆妖怪的取经之路',90,'科幻','六小龄童','2k','杨杰','莱昂纳多'))
this.medias.push(new Videos('蜘蛛侠',3000,'被蜘蛛咬了一口',140,'科幻','蜘蛛','4k','莱昂纳多','莱昂纳多'))
this.medias.push(new Audio('传奇',200,'没听过不知道',6,'王菲','冰冰','坤坤','花花'))
this.medias.push(new Audio('青花瓷',300,'一个瓷器',4,'方文山','闪闪','坤坤','草草'))
this.medias.push(new Videos('乡村爱情故事',4048,'四个老头打架',220,'爱情','刘能','高清','赵本山','赵本山'))
this.medias.push(new Videos('猪猪侠',4077,'一只猪的故事',300,'动画','猪猪侠','1080','海燕','莱昂纳多'))
this.medias.push(new Audio('张三的歌',200,'法外狂徒',3,'民法典','蔡坤','坤坤','绿绿'))
this.medias.push(new Videos('喜人奇妙夜',20480,'喜剧',4800,'喜剧','洋洋','4k','莱昂纳多','莱昂纳多'))
this.medias.push(new Audio('泡沫',300,'悲伤的音乐',3,'邓紫棋','邓紫棋','邓紫棋','邓紫棋'))
this.medias.push(new Videos('明日之星',100,'综艺',60,'综艺','明星','4k','莱昂纳多','莱昂纳多'))
this.medias.push(new Audio('江南',300,'style',4,'陈博','蔡坤','博博','红红'))
}
build() {
Column(){
Text(this.message).fontSize(30)
List({space:10}){
ForEach(this.medias,(md:Medias,index)=>{
ListItem(){
if(md instanceof Audio){ //音频
Column(){
Row(){
// 音频: 名字 大小 简介 时长 作曲 作词 原唱 翻唱
Text(`歌名:${md.name}`)
Text(`大小:${md.size}`)
Text(`时长:${md.times}`)
}.width('100%').height(50).justifyContent(FlexAlign.SpaceBetween)
Row(){
Text(`作词:${md.zq}`)
Text(`作词:${md.zc}`)
Text(`原唱:${md.yc}`)
Text(`翻唱:${md.fc}`)
}.width('100%').height(50).justifyContent(FlexAlign.SpaceBetween)
Row(){
Text(`简介:${md.show}`)
}.width('100%').height(50).justifyContent(FlexAlign.SpaceBetween)
}.width('100%')
.backgroundColor('#ccc')
}else if(md instanceof Videos){ //视频
Column(){
Row(){
// 视频: 名字 大小 简介 时长 类型 主演 画质 导演 制片人
Text(`视频名:${md.name}`)
Text(`大小:${md.size}`)
Text(`时长:${md.times}`)
Text(`类型:${md.type}`)
}.width('100%').height(50).justifyContent(FlexAlign.SpaceBetween)
Row(){
Text(`导演:${md.dy}`)
Text(`主演:${md.zy}`)
Text(`画质:${md.hz}`)
Text(`制片人:${md.zpr}`)
}.width('100%').height(50).justifyContent(FlexAlign.SpaceBetween)
Row(){
Text(`简介:${md.show}`)
}.width('100%').height(50).justifyContent(FlexAlign.SpaceBetween)
}.width('100%')
.backgroundColor('#aaa')
}
}
.swipeAction({
end:this.DelButton(index)
})
})
}.height(400).width('90%')
Row(){
Button('音频')
.type(ButtonType.Normal).width('40%')
.onClick(() => this.isAorV=false)
Button('视频')
.type(ButtonType.Normal).width('40%')
.onClick(() => this.isAorV=true)
}.width('90%').justifyContent(FlexAlign.SpaceBetween).margin({top:10})
if(this.isAorV){ //视频
// 视频: 名字 大小 简介 时长 类型 主演 画质 导演 制片人
Column({space:5}){
Text('视频添加')
Row(){
TextInput({placeholder:'视频名称'}).borderRadius(0).width('30%')
.onChange(val=>this.vd.name=val)
TextInput({placeholder:'大小'}).borderRadius(0).width('30%')
.onChange(val=>this.vd.size=parseFloat(val))
TextInput({placeholder:'时长'}).borderRadius(0).width('30%')
.onChange(val=>this.vd.times=parseFloat(val))
}.width('100%').justifyContent(FlexAlign.SpaceBetween)
Row(){
TextInput({placeholder:'类型'}).borderRadius(0).width('30%')
.onChange(val=>this.vd.type=val)
TextInput({placeholder:'主演'}).borderRadius(0).width('30%')
.onChange(val=>this.vd.zy=val)
TextInput({placeholder:'制片人'}).borderRadius(0).width('30%')
.onChange(val=>this.vd.zpr=val)
}.width('100%').justifyContent(FlexAlign.SpaceBetween)
Row(){
TextInput({placeholder:'画质'}).borderRadius(0).width('30%')
.onChange(val=>this.vd.hz=val)
TextInput({placeholder:'导演'}).borderRadius(0).width('30%')
.onChange(val=>this.vd.dy=val)
TextInput({placeholder:'简介'}).borderRadius(0).width('30%')
.onChange(val=>this.vd.show=val)
}.width('100%').justifyContent(FlexAlign.SpaceBetween)
Button('添加').width('90%')
.onClick(()=>{
//非空验证
if(this.vd.name==''||this.vd.size==0||this.vd.hz==''||this.vd.type==''||this.vd.zy==''||this.vd.zpr==''||this.vd.show==''||this.vd.times==0||this.vd.dy==''){
promptAction.showToast({message:'不能为空'})
}else{
let b:Videos=this.vd
let vd1:Videos=new Videos(b.name,b.size,b.show,b.times,b.zy,b.hz,b.dy,b.zpr,b.type)
this.medias.push(vd1)
promptAction.showToast({message:'音频添加成功'})
}
})
}.width('90%')
}else{ //音频
// 音频: 名字 大小 简介 作曲 作词 原唱 翻唱 时长
Column({space:5}){
Text('音频添加')
Row(){
TextInput({placeholder:'音频名称'}).borderRadius(0).width('45%')
.onChange(val=>this.ad.name=val)
TextInput({placeholder:'大小'}).borderRadius(0).width('45%')
.onChange(val=>this.ad.size=parseFloat(val))
}.width('100%').justifyContent(FlexAlign.SpaceBetween)
Row(){
TextInput({placeholder:'时长'}).borderRadius(0).width('45%')
.onChange(val=>this.ad.times=parseFloat(val))
TextInput({placeholder:'作曲'}).borderRadius(0).width('45%')
.onChange(val=>this.ad.zq=val)
}.width('100%').justifyContent(FlexAlign.SpaceBetween)
Row(){
TextInput({placeholder:'作词'}).borderRadius(0).width('45%')
.onChange(val=>this.ad.zc=val)
TextInput({placeholder:'原唱'}).borderRadius(0).width('45%')
.onChange(val=>this.ad.yc=val)
}.width('100%').justifyContent(FlexAlign.SpaceBetween)
Row(){
TextInput({placeholder:'翻唱'}).borderRadius(0).width('45%')
.onChange(val=>this.ad.fc=val)
TextInput({placeholder:'简介'}).borderRadius(0).width('45%')
.onChange(val=>this.ad.show=val)
}.width('100%').justifyContent(FlexAlign.SpaceBetween)
Button('添加').width('90%')
.onClick(()=>{
//非空验证
if(this.ad.name==''||this.ad.size==0||this.ad.zq==''||this.ad.zc==''||this.ad.yc==''||this.ad.fc==''||this.ad.show==''||this.ad.times==0){
promptAction.showToast({message:'不能为空'})
}else{
let a:Audio=this.ad
let ad1:Audio=new Audio(a.name,a.size,a.show,a.times,a.zq,a.zc,a.yc,a.fc)
this.medias.push(ad1)
promptAction.showToast({message:'音频添加成功'})
}
})
}.width('90%')
}
}
.height('100%')
.width('100%')
}
@Builder DelButton(index:number){
Button('删除')
.type(ButtonType.Normal)
.width('20%')
.height(150)
.onClick(() => {
this.medias.splice(index,1)
})
}
}