仓颉编程入门 -- 包的导入

news2026/4/3 19:44:33

包的导入

一. 概述

在仓颉编程语言中,当你需要利用其他包中的顶层声明或定义时,可以通过import语句来实现。此语句遵循import fullPackageName.itemName的格式,其中fullPackageName代表需要引用的包的完整路径名,而itemName则指定了你希望从该包中导入的具体声明或定义的名字。

重要的是,import语句在源文件中的位置有着明确的要求:它必须出现在包声明(如果存在的话)之后,同时位于任何其他的声明或定义之前。这样的规则确保了代码的结构清晰,使得导入的依赖明确可见,有利于维护和代码阅读。

通过上述方式,仓颉编程语言支持灵活的模块化和代码复用,使得开发者能够方便地构建和组织复杂的项目结构。

package a
import std.math.*
import package1.foo
import {package1.foo, package2.bar}

二. 如何导入

在仓颉编程语言中,当你需要从一个包(fullPackageName)中导入多个顶层声明或定义(itemName)时,可以使用一种更紧凑的语法来简化导入过程。这种语法允许你以集合的形式指定多个项,格式为 import fullPackageName.{itemName[, itemName]}。其中,fullPackageName 是包含这些声明的包的完整路径名,而大括号内的 itemName 列表则是你希望从该包中导入的声明或定义的名字,多个名字之间用逗号分隔。星号()在这里仅用于表示列表的延续,实际上在编写时并不需要逐个列出所有项名后的星号,而是根据需要列出所有要导入的项名即可。

使用这种语法,你可以一次性从同一个包中导入多个项,从而使你的导入语句更加简洁。这样做不仅提高了代码的可读性,还减少了因重复书写包名而可能产生的错误。

import package1.{foo, bar, fuzz}

这等价于

import package1.foo
import package1.bar
import package1.fuzz

在仓颉编程语言中,除了可以通过 import fullPackageName.itemName 的精确语法来导入一个特定包中的顶层声明或定义外,还存在一种更为宽泛的导入方式。这种方式允许你使用 import packageName.* 的语法,一次性将 packageName 包中所有可见的顶层声明或定义全部导入到当前命名空间下。这样做的好处是,你可以快速访问该包中的所有公开成员,无需每次引用时都重复包名前缀。

然而,需要注意的是,虽然这种方式提供了便利,但也可能导致命名冲突或使代码的可读性降低,因为从多个包中导入所有内容可能会让命名空间变得拥挤,难以追踪某个特定声明的来源。因此,在实际开发中,建议谨慎使用 import packageName.* 语法,尤其是在大型项目中。

import package1.*
import {package1.*, package2.*}

在仓颉编程语言中,关于import语句的使用,有几点重要的注意事项需要明确:

  1. 访问修饰符import语句可以被privateinternalprotectedpublic等访问修饰符修饰,以控制导入成员的可见性范围。如果不显式指定访问修饰符,则默认等同于private import,即导入的成员仅在当前文件内可见。
  2. 作用域级别:导入的成员在作用域上的优先级低于当前包声明的成员。这意味着,如果在当前包中也存在与导入成员同名的声明,那么当前包的成员将覆盖导入的成员。
  3. 包名和模块名一致性:当已导出的包的模块名或包名在后续被篡改,导致与导出时指定的名称不一致时,尝试导入该包或模块将会引发错误。这确保了导入的准确性和可靠性。
  4. 可见性要求:只允许导入当前文件可见的顶层声明或定义。如果尝试导入不可见的声明或定义(例如,由于访问权限限制而隐藏的声明),则会在导入处产生编译错误。
  5. 自引用禁止:禁止通过import语句导入当前源文件所在包的声明或定义。这是因为当前文件已经直接位于该包内,无需通过导入来访问其内部成员。
  6. 循环依赖禁止:仓颉编程语言禁止包之间的循环依赖导入。如果编译器检测到包之间存在循环依赖关系,将会报错并阻止项目的构建。这有助于维护项目结构的清晰性和可维护性,避免复杂的依赖关系导致的编译错误和运行时问题。
// pkga/a.cj
package pkga    // Error, packages pkga pkgb are in circular dependencies.
import pkgb.*

class C {}
public struct R {}

// pkgb/b.cj
package pkgb

import pkga.*

// pkgc/c1.cj
package pkgc

import pkga.C // Error, 'C' is not accessible in package 'pkga'.
import pkga.R // OK, R is an external top-level declaration of package pkga.
import pkgc.f1 // Error, package 'pkgc' should not import itself.

public func f1() {}

// pkgc/c2.cj
package pkgc

func f2() {
    /* OK, the imported declaration is visible to all source files of the same package
     * and accessing import declaration by its name is supported.
     */
    R()

    // OK, accessing imported declaration by fully qualified name is supported.
    pkga.R()

    // OK, the declaration of current package can be accessed directly.
    f1()

    // OK, accessing declaration of current package by fully qualified name is supported.
    pkgc.f1()
}

在仓颉编程语言中,关于导入的声明或定义与当前包中顶层声明或定义的重名处理,有明确的规则:

  • 如果导入的声明或定义与当前包中的顶层声明或定义重名,并且这些声明不构成函数重载(即它们不是同名的函数且参数列表不同),则导入的声明或定义会被当前包中的声明或定义所遮盖。这意味着在当前包的作用域内,访问该名称时将直接引用到当前包中的声明或定义,而忽略导入的同名项。
  • 如果导入的声明或定义与当前包中的顶层声明或定义重名,并且这些重名的声明是函数且构成函数重载(即它们具有相同的名称但参数列表不同),则在函数调用时,仓颉编程语言会根据函数重载的规则进行函数决议。这包括根据调用时提供的参数类型、数量和顺序来确定最匹配的函数实现。在这种情况下,编译器会考虑当前包中的函数和导入的函数,以选择最合适的函数进行调用。
// pkga/a.cj
package pkga

public struct R {}            // R1
public func f(a: Int32) {}    // f1
public func f(a: Bool) {} // f2

// pkgb/b.cj
package pkgb
import pkga.*

func f(a: Int32) {}         // f3
struct R {}                 // R2

func bar() {
    R()     // OK, R2 shadows R1.
    f(1)    // OK, invoke f3 in current package.
    f(true) // OK, invoke f2 in the imported package
}

三. 使用 import as 对导入的名字重命名

为了处理不同包之间可能存在的顶层声明重名问题,仓颉编程语言支持使用import as语法对导入的名字进行重命名。这种机制允许开发者在导入不同包中的同名顶层声明时,通过指定一个别名来避免命名冲突。即使没有直接的命名冲突,开发者也可以使用import as来重命名导入的内容,以增加代码的可读性或满足特定的编码风格。

使用import as进行重命名后,当前包中只能使用重命名后的新名字来引用该声明,原名将不再可用。如果重命名后的名字与当前包顶层作用域中的其他名字发生冲突,且这些名字对应的声明均为函数类型,则编译器会根据函数重载的规则来处理这些冲突;否则,将报告重定义的错误,因为不允许在同一作用域内存在两个同名的非函数重载声明。

此外,仓颉编程语言还支持import pkg as newPkgName的形式,允许开发者对包名本身进行重命名。这一特性特别有用,在解决不同模块中可能存在的同名包命名冲突问题时,通过为包指定一个唯一的别名,可以确保每个包都能被正确且无歧义地引用。

// a.cj
package p1
public func f1() {}

// d.cj
package p2
public func f3() {}

// b.cj
package p1
public func f2() {}

// c.cj
package pkgc
public func f1() {}

// main.cj
import p1 as A
import p1 as B
import p2.f3 as f  // OK
import pkgc.f1 as a
import pkgc.f1 as b // OK

func f(a: Int32) {}

main() {
    A.f1()  // OK, package name conflict is resolved by renaming package name.
    B.f2()  // OK, package name conflict is resolved by renaming package name.
    p1.f1() // Error, the original package name cannot be used.
    a()     // Ok.
    b()     // Ok.
    pkgc.f1()    // Error, the original name cannot be used.
}

这种情况可以通过 import as 定义别名或者 import fullPackageName 导入包作为命名空间。

// a.cj
package p1
public class C {}

// b.cj
package p2
public class C {}

// main1.cj
package pkga
import p1.C
import p2.C

main() {
    let _ = C() // Error
}

// main2.cj
package pkgb
import p1.C as C1
import p2.C as C2

main() {
    let _ = C1() // Ok
    let _ = C2() // Ok
}

// main3.cj
package pkgc
import p1
import p2

main() {
    let _ = p1.C() // Ok
    let _ = p2.C() // Ok
}

在开发大型项目时,经常遇到包间依赖复杂的情况。假设包p2广泛使用了从包p1中导入的声明,当另一个包p3想要使用p2提供的功能时,如果p3还需要知道并导入p2所依赖的p1中的具体声明,这无疑增加了项目的复杂性和维护难度。为了简化这一过程,仓颉编程语言允许通过特定的import机制来实现声明的“重导出”。

在仓颉编程语言中,import语句可以被privateinternalprotectedpublic等访问修饰符修饰。这些修饰符不仅控制了导入内容在当前包或模块中的可见性,还决定了这些内容是否可以被其他包或模块通过当前包间接访问。

  • public import:当importpublic修饰时,导入的成员将被视为当前包对外提供的一部分接口,其他包可以通过导入当前包来间接访问这些从其他包(如p1)导入的声明,前提是这些导入的成员在当前包中没有因为名称冲突或被遮盖而不可用。
  • protected import:类似于protected访问修饰符在其他上下文中的用法,被protected修饰的import使得导入的成员在当前模块内部(包括其子包)可访问,但对外部包不可见。
  • internal import:此修饰符下的导入内容在当前包及其子包(递归地包括所有子包的子包)内可访问。然而,需要注意的是,这里的“外部都可访问”描述对于internal import并不准确;实际上,它仅限于包内和子包内,非当前包的直接访问仍需要显式导入。
  • private import:默认的import修饰符,如果不显式指定其他修饰符,则等同于private import。这意味着导入的内容仅在当前文件内部可见,对其他文件或包不可访问。

重要的是要理解,即使某个导入被标记为publicprotectedinternal,它也只是在当前包或模块的上下文中提供了访问权限的调整,而并非自动将导入的声明暴露给所有外部包。外部包仍然需要显式地通过当前包来访问那些被重导出的内容。

package a

public let x = 0
public import a.b.f

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2048417.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何在 3 分钟内免费在 AWS 上运行 RStudio

欢迎来到雲闪世界。谈到数据分析,我有理由从本地计算机迁移到云端。最突出的是,您可以运行无限数量的机器,而无需拥有或维护它们。此外,您可以在几分钟内根据需要扩大或缩小规模。如果您选择运行 t2.micro 服务器,您可…

ant design pro 如何去保存颜色

上图 就是实现这样的效果 后端是这样的,这个颜色肯定是存到字符串里的 这是第一步 import mongoose, { Schema, Document } from mongoose;interface IDiscountCard extends Document {title: string;subtitle: string;image: string;shopUrl: string;bgColor: s…

望繁信科技荣膺上海市浦东新区博士后创新实践基地称号

近日,上海望繁信科技有限公司(简称“望繁信科技”)凭借在大数据流程智能领域的卓越表现,成功入选上海市浦东新区博士后创新实践基地。这一荣誉不仅是对望繁信科技创新能力和技术实力的高度认可,也标志着公司在推动产学…

基于springboot养老院管理系统pf

TOC springboot332基于springboot养老院管理系统pf 第1章 绪论 1.1选题动因 当前的网络技术,软件技术等都具备成熟的理论基础,市场上也出现各种技术开发的软件,这些软件都被用于各个领域,包括生活和工作的领域。随着电脑和笔记…

Hive3:简单ETL实操案例

一、ETL概念简介 ETL: E,Extract,抽取 T,Transform,转换 L,Load,加载 从A抽取数据(E),进行数据转换过滤(T),将结果加载到B(L),就是ETL 二、情景描述 聊天平…

数据结构(邓俊辉)学习笔记】优先级队列 04——完全二叉堆:插入与上滤

文章目录 1. 上滤2. 实例3. 实现4. 效率 1. 上滤 好,接下来我们就来学习在一个完全二叉堆中,如何有效地插入一个新的元素。我们将会看到插入过程中的核心技巧是所谓的 ”上滤“ 过程。 为了在完全二叉堆中引入一个新的词条 e,我们只需在物…

【网络编程】TCP实现网络通信(C语言、Ubuntu实现)

TCP服务器通信模型:(分为以下6个步骤) 1、sfd socket(); //创建一个用于连接的套接字文件描述符 2、bind(); //为服务器套接字绑定ip地址和端口号,为了让客户端额能够找到服务器 3、l…

C++第三十七弹---深入理解红黑树:旋转、着色与性质维护

✨个人主页: 熬夜学编程的小林 💗系列专栏: 【C语言详解】 【数据结构详解】【C详解】 目录 1 红黑树 1.1 红黑树的概念 1.2 红黑树的性质 1.3 红黑树节点的定义 1.4 红黑树结构 1.5 红黑树的插入操作 1.6 红黑树的验证 1.7 红黑树与…

XSS的一些相关案例及DOM破坏的案例

目录 第一关 第二关 第三关 第四关 第五关 第六关 第七关 第八关(DOM破坏) 网址:XSS Game - Learning XSS Made Simple! | Created by PwnFunction 第一关 来分析一下代码 就是一个URL类里进行一个get接收参数(somebody)如果没参数就默认接收(Somebody)这…

C++仿C#实现事件处理

测试 #include "beacon/beacon.hpp" #include <cstdio> #include <thread>class mouseEvent : public beacon::args { public:mouseEvent(int x, int y) : x(x), y(y) {}int x, y; };class object : public beacon::sender { public:};class mouseHandl…

6大企业必备的公司常用的加密软件推荐|2024公司常用加密软件推荐!

2024年上半年&#xff0c;企业对于数据加密的需求日益增长&#xff0c;以确保数据在存储和传输过程中的安全性。以下是六款企业常用的加密软件推荐&#xff0c;它们各具特色&#xff0c;能够满足不同企业的加密需求&#xff1a; 1.NordLocker&#xff1a; 特点&#xff1a;它是…

【Linux系列】telnet使用入门

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

什么是视频比特率?与视频时长是什么关系

​ ‌比特率是指单位时间内传输或处理的比特的数量&#xff0c;单位为‌bps(‌bit per second)。‌ 比特率经常用于描述在电信和计算领域中数据传输的速度&#xff0c;也可以作为衡量音频和视频文件数据率的指标。比特率越高&#xff0c;传送的数据越大&#xff0c;音频或视频…

Ubuntu安装Anaconda3

本文详细阐述了在 Ubuntu 系统中安装 Anaconda3 的完整流程。包括 Anaconda3 安装包的获取途径&#xff0c;具体安装过程中的每一个步骤及注意事项&#xff0c;还有安装后的环境变量设置和安装成功的验证方法。旨在为 Ubuntu 用户提供清晰、易懂且准确的 Anaconda3 安装指南&am…

Windows Microsoft Edge 浏览器 配置【密码】

在浏览 Web 时&#xff0c;Microsoft Edge 可以轻松保存密码。 在桌面或移动设备上的 Edge 浏览器中输入新密码时&#xff0c;Microsoft Edge 会询问你是否要记住用户名和密码。 下次访问该网站时&#xff0c;浏览器将完成帐户信息的填写。 如果使用 Microsoft 帐户登录到 Edg…

重塑业务生态,Vatee万腾平台:引领行业变革的新引擎

在数字经济浪潮汹涌的今天&#xff0c;传统行业的边界正被不断模糊与重塑&#xff0c;新兴技术如云计算、大数据、人工智能等正以前所未有的速度改变着商业世界的面貌。在这一背景下&#xff0c;Vatee万腾平台应运而生&#xff0c;以其独特的创新模式和强大的技术实力&#xff…

i.MX6裸机开发(1):环境搭建

1. 熟悉sdk SDK&#xff08;Software Development Kit&#xff09;是NXP针对其官方评估 版的软件开发包&#xff0c;可以在NXP的官网下载得到。SDK中包含了 各种程序范例&#xff0c;我们心心念念的固件库也包含在它里边。 NXP官网链接&#xff1a;https://www.nxp.com 未登录…

Camera基础知识系列(2)——对焦和变焦

目录 一. 引言 二. 对焦 定义&#xff1a; 原理 三. 变焦 定义 用途 四. 总结 一. 引言 这一节简单聊一下对焦和变焦&#xff0c;这两个是摄影种出现的高频词&#xff0c;但这里把它们放一起讲&#xff0c;主要还是因为它们在字面上就一字之差&#xff0c;初次接触…

XSS DOM破坏实战案例

目录 案例一 思考 源码分析 查找问题 实现 案例二 查看源码 问题查找 实现 实验环境&#xff1a;DOM clobbering | Web Security Academy (portswigger.net) 案例一 里面是一篇篇的博客&#xff0c;点击进去里面是一些评论 思考 尝试一些常规的xss 没什么效果... 他将…

Java、python、php版的企业单位考勤打卡管理系统的设计与实现(源码、调试、LW、开题、PPT)

&#x1f495;&#x1f495;作者&#xff1a;计算机源码社 &#x1f495;&#x1f495;个人简介&#xff1a;本人 八年开发经验&#xff0c;擅长Java、Python、PHP、.NET、Node.js、Android、微信小程序、爬虫、大数据、机器学习等&#xff0c;大家有这一块的问题可以一起交流&…