当前位置: 首页 > news >正文

HarmonyOS ArkTS 面向对象编程:class、interface 完全指南

文章目录

    • 前言
    • 一、class:封装数据与行为
      • 1.1 最基本的类定义
      • 1.2 本项目中的 MapUtil 类分析
    • 二、interface:定义数据形状
      • 2.1 interface 的用途
      • 2.2 interface vs class vs type 的选择
    • 三、继承:复用和扩展类
      • 3.1 extends 继承
      • 3.2 implements:类实现接口
    • 四、访问控制:public/private/protected
    • 五、静态成员:不需要实例的工具方法
    • 总结

前言

在 HarmonyOS 开发中,代码不可能全部堆在一个文件里。**类(class)接口(interface)**是组织代码、实现复用的核心工具。本项目中的MapUtilPermissionsUtilCalculateUtilLogger等都是精心设计的类,它们让复杂逻辑封装成简洁的 API。

本篇通过分析项目中的类设计,结合可运行示例,带你掌握 ArkTS 面向对象编程的精髓。

一、class:封装数据与行为

1.1 最基本的类定义

// 定义一个加油站类classGasStation{// 属性(成员变量)id:string;name:string;latitude:number;longitude:number;brand:string;isOpen:boolean;// 构造函数constructor(id:string,name:string,lat:number,lng:number,brand:string){this.id=id;this.name=name;this.latitude=lat;this.longitude=lng;this.brand=brand;this.isOpen=true;// 默认开业}// 方法:获取格式化的坐标字符串getCoordinateString():string{return`${this.latitude.toFixed(4)},${this.longitude.toFixed(4)}`;}// 方法:判断是否是中国石化isSinopec():boolean{returnthis.brand==='中国石化';}// 方法:切换营业状态toggleOpen():void{this.isOpen=!this.isOpen;}// toString 方便调试toString():string{return`[${this.brand}]${this.name}@${this.getCoordinateString()}(${this.isOpen?'营业中':'休息中'})`;}}// 创建实例conststation1=newGasStation('001','望京加油站',40.0046,116.4823,'中国石化');conststation2=newGasStation('002','朝阳加油站',39.9219,116.4386,'中国石油');console.log(station1.toString());// [中国石化] 望京加油站 @ 40.0046, 116.4823 (营业中)console.log(station1.isSinopec());// truestation1.toggleOpen();console.log(station1.isOpen);// false

1.2 本项目中的 MapUtil 类分析

@Observed// ← HarmonyOS 特有:使类属性变化可被观察exportclassMapUtil{// 方法1:坐标转换(异步)publicasyncconvertToGCJ02(latitude:number,longitude:number):Promise<mapCommon.LatLng>{lettheWGS84Position:mapCommon.LatLng={latitude,longitude};lettheGCJ02Position:mapCommon.LatLng=awaitmap.convertCoordinate(mapCommon.CoordinateType.WGS84,mapCommon.CoordinateType.GCJ02,theWGS84Position);returntheGCJ02Position;}// 方法2:移动地图到指定位置publicmoveToCurrentPosition(latitude:number,longitude:number,mapController:map.MapComponentController):void{letcameraPosition:mapCommon.CameraPosition={target:{latitude,longitude},zoom:15.9};letcameraUpdate:map.CameraUpdate=map.newCameraPosition(cameraPosition);mapController?.animateCamera(cameraUpdate,500);}// 方法3:获取当前位置asyncgetMyLocation():Promise<geoLocationManager.Location>{returnawaitgeoLocationManager.getCurrentLocation();}// ... 更多方法}// 导出单例实例(整个应用共享一个 MapUtil 实例)exportconstmapUtil:MapUtil=newMapUtil();

设计亮点:

  • @Observed让类实例的属性变化能触发 UI 更新
  • public关键字显式声明公开方法
  • 导出单例mapUtil,避免重复创建实例

二、interface:定义数据形状

2.1 interface 的用途

interface只定义"形状"(有哪些属性和方法),不包含实现逻辑:

// 定义加油站的数据接口interfaceIStation{id:string;name:string;latitude:number;longitude:number;image:Resource;// HarmonyOS 资源类型addr:string;}// 定义可定位的接口interfaceILocatable{latitude:number;longitude:number;getCoordinateString():string;}// 定义可收藏的接口interfaceIFavoritable{isFavorite:boolean;toggleFavorite():void;}

2.2 interface vs class vs type 的选择

特性interfaceclasstype
只描述形状❌(有实现)
包含方法实现
可以实例化
可以继承/实现extendsextends
适用场景API类型约束、数据形状工具类、单例复杂联合类型
// 场景1:用 interface 约束函数参数(推荐)interfaceMapConfig{zoom:number;latitude:number;longitude:number;showMyLocation?:boolean;// 可选属性}functioninitMap(config:MapConfig):void{console.log(`初始化地图,缩放级别:${config.zoom}`);}initMap({zoom:16,latitude:39.9,longitude:116.4});// ✅initMap({zoom:16});// ❌ 缺少必需属性// 场景2:用 type 定义联合类型(推荐)typeMapType='standard'|'satellite'|'terrain';typeLoadStatus='loading'|'success'|'error'|'empty';// 场景3:用 class 封装逻辑(推荐)classMapManager{privatestaticinstance:MapManager;staticgetInstance():MapManager{if(!MapManager.instance){MapManager.instance=newMapManager();}returnMapManager.instance;}init(config:MapConfig):void{// 初始化逻辑}}

三、继承:复用和扩展类

3.1 extends 继承

// 基础工具类classBaseUtil{protectedtag:string;constructor(tag:string){this.tag=tag;}// 基础日志方法protectedlog(level:string,message:string):void{consttimestamp=newDate().toISOString();console.log(`[${timestamp}][${level}][${this.tag}]${message}`);}info(message:string):void{this.log('INFO',message);}error(message:string):void{this.log('ERROR',message);}}// 地图工具:继承基础工具类classExtendedMapUtilextendsBaseUtil{privatezoom:number=16;constructor(){super('MapUtil');// 调用父类构造函数}// 新增方法setZoom(zoom:number):void{if(zoom<3||zoom>21){this.error(`缩放级别${zoom}超出范围 [3, 21]`);return;}this.zoom=zoom;this.info(`缩放级别设置为${zoom}`);}getZoom():number{returnthis.zoom;}// 重写父类方法info(message:string):void{// 在基础 log 前加上地图专属前缀super.log('MAP-INFO',`🗺️${message}`);}}constmapUtil2=newExtendedMapUtil();mapUtil2.info('地图初始化完成');// 🗺️ 地图初始化完成mapUtil2.setZoom(25);// ERROR: 缩放级别超出范围mapUtil2.setZoom(15);// 🗺️ 缩放级别设置为 15

3.2 implements:类实现接口

interfaceICalculator{calculate(a:number,b:number):number;format(result:number):string;}// 距离计算器classDistanceCalculatorimplementsICalculator{calculate(lat1:number,lng1:number):number{// 简化实现returnMath.sqrt(Math.pow(lat1,2)+Math.pow(lng1,2));}// 必须实现接口定义的所有方法format(result:number):string{return`${result.toFixed(1)}km`;}}// 油价计算器(同一接口,不同实现)classPriceCalculatorimplementsICalculator{calculate(liters:number,pricePerLiter:number):number{returnliters*pricePerLiter;}format(result:number):string{return`¥${result.toFixed(2)}`;}}

四、访问控制:public/private/protected

classStationRepository{// private:只能在类内部访问private_stations:GasStation[]=[];private_isLoaded:boolean=false;// protected:类内部和子类可访问protectedmaxCount:number=100;// public:外部可访问(默认就是 public)publicgetstations():GasStation[]{returnthis._stations;}publicgetisLoaded():boolean{returnthis._isLoaded;}// 私有方法:内部逻辑不对外暴露privatevalidate(station:GasStation):boolean{returnstation.name.length>0&&station.latitude!==0;}// 公开方法:对外提供的 APIpublicadd(station:GasStation):boolean{if(!this.validate(station)){returnfalse;}if(this._stations.length>=this.maxCount){returnfalse;}this._stations.push(station);returntrue;}publicfindById(id:string):GasStation|undefined{returnthis._stations.find(s=>s.id===id);}}constrepo=newStationRepository();// repo._stations // ❌ 无法访问 private// repo.maxCount // ❌ 无法访问 protected(在类外)console.log(repo.stations);// ✅ 通过 getter 访问

五、静态成员:不需要实例的工具方法

// CalculateUtil 使用了静态方法模式(不需要 new)classCalculateUtil{// static 方法:直接通过类名调用,不需要创建实例publicstaticgetDistance(lat1:number,long1:number,lat2:number,long2:number):string{// ... 计算距离returndistance.toFixed(1);}}// 调用方式:直接用类名constdist=CalculateUtil.getDistance(39.9,116.4,40.0,116.5);// 不需要 new CalculateUtil()// 静态常量classConstants{staticreadonlyFONT_SIZE_16=16;staticreadonlyFONT_WEIGHT_700=700;staticreadonlyFULL_PERCENT='100%';}

总结

ArkTS 的类和接口是构建大型 HarmonyOS 应用的基础:class封装数据和行为,interface约束数据形状,extends实现继承复用,访问控制保证封装性,静态成员提供无需实例化的工具方法。本项目中的四个工具类(MapUtil、CalculateUtil、PermissionsUtil、Logger)完美诠释了面向对象设计原则,是学习类设计的绝佳参考。

http://www.cnnetsun.cn/news/2833438.html

相关文章:

  • 5 步搞定!第三方代付入账操作流程
  • (毕业必看)实测好用的AI写作辅助软件,毕业党收藏备用
  • MySQL数据库的分库分表实战
  • MyBatis-Plus 嵌套查询实战
  • Zotero-GPT插件API调用故障排查:3步解决AI功能失效问题
  • 原神FPS解锁工具:终极免费突破60帧限制完整指南
  • 如何利用Solaar在Linux上完全掌控罗技设备:5个核心技术深度解析与实战指南
  • 沉迷 Vibe coding 后我幡然醒悟:为什么可持续开发要回归半古法编程
  • 2027考研资料|什么时候出|资料库
  • Bad luck to your mother.
  • Qt写的轻量级职工信息链表管理工具,支持文件存取和三字段排序
  • Microsoft Teams的白板功能
  • PN7642 NFC开发板实战:从硬件连接到射频测试全流程指南
  • Cursor Pro破解工具终极指南:3分钟永久免费激活AI编程助手
  • 【新手保姆级教程】详解 OpenClaw v2.7.9 安装流程,梳理部署避坑要点
  • Linux file命令详解
  • Agent 市场血雨腥风,MiniMax 多 Agent 架构引领变革,重塑行业格局?
  • 腾讯会议同传工具评测与选型指南
  • DDD-018:应用服务与事务脚本
  • 103、飞控仿真环境搭建:Gazebo与PX4 SITL
  • 【Ubuntu】使用ffmpeg解析m3u8网页视频
  • 7大真实任务实测 Opus 4.8、Gemini 3.5 Flash、GPT-5.5、Qwen3.7-Max
  • Spring依赖注入的方式
  • Gemini 3.5 深度实测|碾压前代!多模态+工程协作落地,重新定义AI开发辅助上限
  • 深度解析飞算 JavaAI 智能引导的五大步骤:AI 是如何把一句需求变成工程级 Java 代码的?
  • 洛雪音乐音源配置终极指南:从零搭建专业级音乐库的完整方案
  • 网规笔记真题解析:2024年11月软考网规案例分析
  • 如何让机器人在未知环境中实时构建3D地图?RTAB-Map技术深度解析
  • MyBatis-Plus 性能分析实战
  • nmap:网络扫描祖师爷,二十多年过去还是没对手