仓颉语言包示例:演示包结构和访问修饰符的使用

发布于:2025-08-12 ⋅ 阅读:(22) ⋅ 点赞:(0)

仓颉语言包示例:演示包结构和访问修饰符的使用

本文通过仓颉语言示例展示了包结构和访问修饰符的使用。示例包含demo8主包及其子包business和two,演示了public、internal、protected和private四种访问修饰符的控制效果。其中PaymentProcessor类作为基类,其子类CreditProcessor展示了继承关系中访问权限的控制,而ExternalService则验证了跨包访问的边界限制。主程序main.cj整合调用各模块功能,体现了仓颉语言的模块化设计、封装性和面向对象特性。示例重点验证了protected与public的区别,以及跨模块访问时修饰符的控制作用,展示了仓颉语言在代码组织和访问控制方面的核心能力。

顺便提示,如何在CodeArts IDE for Cangjie 创建的工程(Project) 源码根目录src上新建源码文件或子目录(子包)?
右击src可见相关快捷菜单命令项。 
仓颉编程语言中的包的基础知识可见 https://blog.csdn.net/cnds123/article/details/149782471

包结构如下:

demo8
  │
  src/
  ├── main.cj         // 入口
  ├── business/         // business包
  │      ├── finance.cj  // business包的finance.cj
  │      └── utils.cj    // business包的utils.cj
  └── two/        // two包
          └── other.cj    // two包的other.cj

1.business/utils.cj 的源码:

package demo8.business

//注意,声明为public 和open 才能被其他包访问
public open class PaymentProcessor {
    private var transactionId: Int64 = 0
    internal var merchant = "Default"
    protected var feeRate: Float64 = 0.03
    public var currency = "USD"
    
    public PaymentProcessor() {}
    public init(currency: String) {
        this.currency = currency
    }
}

internal class SecurityUtils {
    public func encrypt(data: String): String {
        return "ENCRYPTED:${data}"
    }
}

2. business/finance.cj  的源码:

package demo8.business

//  声明为 public 
public class CreditProcessor <: PaymentProcessor {
    // public init() {
    //     super()
    // }
    
    // 整数版本
    public func process(amount: Int64) {
        process(Float64(amount))
    }
    
    // 浮点数版本
    public func process(amount: Float64) {
        let fee = amount * feeRate
        println("收取 ${fee} ${currency}")
        merchant = "CreditCo"
        
        let utils = SecurityUtils()
        println(utils.encrypt("敏感数据"))
    }
}

3.two/lib.cj 的源码:

package demo8.two

import demo8.business.PaymentProcessor  // 跨包导入business包的类PaymentProcessor

public class ExternalService {
    public func demo() {
        let processor = PaymentProcessor()
        processor.currency = "JPY"  // 修改为日元测试
        println("== 跨包访问测试 ==")
        println("设置货币: ${processor.currency}")
        
        // 以下尝试会编译失败(取消注释测试)
        // processor.merchant = "Tokyo"  // ✗ internal不可访问       
    }
}

4. 入口主程序 (main.cj)源码

package demo8

import demo8.business.PaymentProcessor // 导入business包的类PaymentProcessor
import demo8.business.CreditProcessor // 导入business包的类 CreditProcessor
import demo8.two.ExternalService  // 导入two包的类ExternalService

main() {    
    let base = PaymentProcessor() // 创建对象    
    let credit = CreditProcessor() // 创建对象
    
    // 测试整数调用
    println("整数付款测试:")
    credit.process(100)
    
    // 测试浮点数调用
    println("\n浮点数付款测试:")
    credit.process(99.99)
    
    // 测试货币设置
    println("\n货币设置测试:")
    let euroProcessor = PaymentProcessor("EUR") // 创建对象
    println("新货币: ${euroProcessor.currency}")

    // 调用跨包服务
    println("\n调用外部服务:")
    ExternalService().demo()  // 这句和下面两句等价
    // let tempObj =  ExternalService()
    // tempObj.demo()
}

编译运行请跨部分

运行输出
整数付款测试:
收取 3.000000 USD 
ENCRYPTED:敏感数据

浮点数付款测试:   
收取 2.999700 USD 
ENCRYPTED:敏感数据

货币设置测试:     
新货币: EUR

调用外部服务:
== 跨包访问测试 ==
设置货币: JPY

分析说明提要:

这个工程完美展示了仓颉语言的三大核心能力:

    模块化:通过包实现代码组织

    封装性:精细的访问控制(private/internal/protected/public)

    面向对象:类继承、方法重载、多态

整个工程以 demo8 为主包,通过子包划分功能模块,符合模块化设计原则:

  •  主入口:src/main.cj 作为程序入口,负责统筹调用各模块功能。

  •  业务核心包:src/business/ 封装支付相关的核心逻辑,包含:

        utils.cj:定义基础类(PaymentProcessor)和包内工具类(SecurityUtils)。

        finance.cj:实现具体支付方式(CreditProcessor,继承自 PaymentProcessor)。

  •  外部服务包:src/two/ 模拟跨包调用场景(ExternalService),用于验证跨包访问规则。请留意other.cj其中有跨包导入。

代码文件要点说明

finance.cj中的CreditProcessor 类成功访问了 utils.cj 中的父类PaymentProcessor的 protected 和 internal 成员,完成费用计算和商户名称修改。

utils.cj中的类SecurityUtils 在同包内正常使用,完成数据加密。

other.cj中跨包的类 ExternalService 只能修改 public 的 currency,无法触碰 internal 成员。

主程序main.cj通过导入不同包的类,串联起所有功能,体现了模块化协作的有效性。

访问修饰符的核心作用与验证

仓颉语言的 4 种访问修饰符(private、internal、protected、public)在示例中被充分验证。

控制成员的可见性,共 4 种

修饰符      可见范围

private     仅当前类内部

internal    当前包及子包(默认)

protected   当前模块及当前类的子类

public      模块内外均可见

【在仓颉(Cangjie)语言里,包(package) 与 模块(module) 的对应关系可以一句话总结为:

    一个模块 = 一个 cjpm (Cangjie Package Manager:仓颉包管理器)项目 = 一个仓颉独立的构建和分发单元。

    包(package)只是模块内部的“命名空间”层级,用来组织源码目录。】

protected 和 public 的区别

protected

  • 不仅是“能访问”,还隐含“可继承”——子类可以覆写该成员。

  • 同时受“模块”限制:别的模块即使继承了该类,也看不见 protected 成员;

  • 只有同一个模块内的子类才能继承/覆写。

public

  • 只是“能看见”,不隐含可继承;

  • 任何模块都能看见,但覆写仍需要 open + override。

  • 没有模块边界限制,跨模块也能用。

【在仓颉里,“跨模块”就是跨 cjpm 项目。

你可以把 A 项目编译成 .cjpm(库),然后在 B 项目里把它声明成依赖,就能“跨模块”使用。】

类继承与访问权限的配合

示例中 CreditProcessor <: PaymentProcessor 的继承关系,进一步验证了访问修饰符在继承场景的作用:

1.继承前提:PaymentProcessor 必须声明为 open 才能被继承(仓颉中类默认不可继承,需显式 open),且为 public 才能被跨包继承。

2.子类访问父类成员:CreditProcessor 作为子类,可访问父类的 protected(feeRate)、internal(merchant)、public(currency)成员,但无法访问 private(transactionId),符合权限规则。

3.方法重载:CreditProcessor 重载了 process 方法(整数 / 浮点数版本),均声明为 public,确保外部可调用。

跨包调用的边界控制

two/other.cj的 ExternalService 模拟了跨包访问场景,清晰展示了包间访问的边界:

  •  允许访问:PaymentProcessor类 的 public 成员(如 currency)和构造函数。

  •  禁止访问:PaymentProcessor 类的 internal 成员(如 merchant,注释代码编译失败),体现了 “包内私有” 的隔离性。


网站公告

今日签到

点亮在社区的每一天
去签到