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

仓颉编程语言青少年基础教程:Interface(接口)

仓颉编程语言青少年基础教程:Interface(接口)

Interface(接口)的定义和使用

接口用来定义一个抽象类型,它不包含数据,但可以定义类型的行为。一个类型如果声明实现某接口,并且实现了该接口中所有的成员,就被称为实现了该接口。

接口的成员可以是抽象的,这意味着接口只规定了这些成员的类型信息(即“做什么”),但不提供具体的实现(即“怎么做”),所有具体实现都由实现类完成

接口支持继承、多实现、静态成员、泛型成员等高级特性。实现接口的类型自动成为该接口的子类型,可以多态使用。

基本接口定义与实现示例:

// 定义接口:声明一个实例函数
interface Flyable {func fly(): Unit  // 抽象方法,无实现
}// 实现接口:Bird类实现Flyable
class Bird <: Flyable {public func fly(): Unit {  // 必须实现fly()println("鸟扇动翅膀飞行")}
}// 实现接口:Plane类实现Flyable
class Plane <: Flyable {public func fly(): Unit {println("飞机靠引擎飞行")}
}// 测试:接口作为参数,接收所有实现类
func letItFly(f: Flyable): Unit {f.fly()
}main() {let bird = Bird()let plane = Plane()letItFly(bird)  // 输出:鸟扇动翅膀飞行letItFly(plane) // 输出:飞机靠引擎飞行
}

编译运行截图:

定义接口语法

[修饰符] interface接口名 {
    // 成员列表(函数、属性、操作符重载)
}

注意

  • 关键字:interface 是接口声明的固定起始关键字。

  • 修饰符(可选):interface 关键字前的修饰符仅支持 open 或 sealed,默认隐含 open 语义(无需显式声明,因为接口本身就隐含了 open 的语义)。sealed 修饰符(非访问修饰符)示该 class 或 interface 只能在当前包内被继承或实现。

  • 接口名:符合仓颉标识符规范(如 Flyable、NamedType)。

  • 成员列表:接口的核心,定义抽象行为,默认均为 public(不可显式添加其他访问修饰符,如 private/protected),并且接口成员默认隐式为 open(可被实现 / 继承);成员可以是没有实现体的抽象声明(必须由实现类型提供实现),也可以是带有默认实现的具体实现(实现类型可以选择重写或直接使用)。成员类型支持三类:

  • 实例成员函数 / 操作符重载函数

  • 静态成员函数 / 操作符重载函数

  • 成员属性(仅约定类型和可变性 mut)

接口的实现语法

class/struct/enum 类型名 <: 接口1 & 接口2 & ... {
    // 必须实现接口所有未提供默认实现的成员
    [override] [public] func 接口函数名(参数列表): 返回类型 {
        // 实现(返回类型可为接口指定类型的子类型)
    }
    
    [static] [redef] [public] func 接口静态函数名(参数列表): 返回类型 {
        // 实现
    }
}

其中:

  • 使用 <: 符号表示“实现”或“继承自”。实现多个接口时,用 & 连接。

  • 实现类型必须为接口中的所有抽象成员(没有默认实现的)提供具体的、public 的实现。

  • 如果接口中的成员函数或操作符重载函数的返回值类型是 class 类型,那么允许实现函数的返回类型是其子类型。

接口继承规则

子接口

  • 对父接口“已有默认实现”的成员:必须给出新的默认实现(override 可选)。

  • 对父接口“无默认实现”的成员:可仅声明,也可给默认实现(override 可选)。

下面给出一个完整的接口示例:

interface Vehicle {func start(): Unitfunc stop(): Unit {println("Vehicle stopped") // 默认实现}
}interface Electric {func charge(): Unit
}// Car 实现 Vehicle 和 Electric 接口
class Car <: Vehicle & Electric {public var speed: Float64 = 0.0public override func start(): Unit {println("Car started")}// 使用默认的stop方法public override func charge(): Unit {println("Car is charging")}
}main() {let myCar = Car()myCar.start() // 输出: Car startedmyCar.stop()  // 输出: Vehicle stopped (默认实现)myCar.charge() // 输出: Car is charging// 多态let vehicle: Vehicle = myCarvehicle.start()  // 输出: Car started   
}

编译运行输出:

Car started
Vehicle stopped
Car is charging
Car started  

几点重要示例说明:

1. 静态成员与默认实现

接口的静态成员可强制所有实现类型提供类型相关的行为,支持默认实现。示例:

// 定义带静态成员的接口(带默认实现)
interface NamedType {static func getTypeName(): String {  // 静态成员默认实现"未知类型"}
}// 实现接口:无需重写静态成员(直接继承默认实现)
class Cat <: NamedType {}// 实现接口:重写静态成员
class Dog <: NamedType {public static func getTypeName(): String {  // 自定义实现"Dog"}
}main() {println(Cat.getTypeName())  // 继承默认实现:输出 未知类型println(Dog.getTypeName())  // 自定义实现:输出 Dogprintln(NamedType.getTypeName())  // 直接访问接口静态成员:输出 未知类型
}

注意:

抽象静态成员:实现类型必须提供实现。不能通过接口名直接调用(InterfaceName.staticMethod() 会报错)。

有默认实现的静态成员:实现类型可以不重写该成员。可以通过接口名和实现类型名调用(InterfaceName.staticMethod() 和 ImplementingClass.staticMethod() 均可)。

2. 接口继承与多接口实现

接口可继承其他接口,实现类需满足所有父接口的规范。示例:

// 父接口1:加法行为
interface Addable {func add(other: Int64): Int64
}// 父接口2:减法行为
interface Subtractable {func sub(other: Int64): Int64
}// 子接口:继承两个父接口,新增乘法行为
interface Calculable <: Addable & Subtractable {func mul(other: Int64): Int64
}// 实现子接口:需同时实现add、sub、mul
class MyNumber <: Calculable {var value: Int64 = 0public func add(other: Int64): Int64 {value + other}public func sub(other: Int64): Int64 {value - other}public func mul(other: Int64): Int64 {value * other}
}main() {let num = MyNumber()num.value = 10println(num.add(5))  // 15println(num.sub(3))  // 7println(num.mul(2))  // 20
}

3.冲突与解决

多接口成员默认实现冲突时,实现类型必须手动实现——必须提供自己的实现。示例:

// 接口1:带默认实现的say()
interface Greeter1 {func say(): String {"你好"}
}// 接口2:带默认实现的say()
interface Greeter2 {func say(): String {"Hello"}
}// 同时实现两个接口:say()默认实现冲突,必须手动实现
class Person <: Greeter1 & Greeter2 {public func say(): String {"既要你好,也要Hello"  // 自定义实现解决冲突}
}main() {let p = Person()println(p.say())  // 输出:既要你好,也要Hello
}

4. sealed 修饰符

表示该 class 或 interface 只能在当前包内被继承或实现。

在仓颉语言中,sealed 修饰符属于非访问修饰符(也称为 “功能修饰符”),而非访问修饰符(如 public、private 等)。

示例项目/工程目录结构:
demo9/
└── src
    ├─A
    │   ├── a1.cj       
    │   └── a2.cj 
    ├─B
    │   └── b1.cj 
    └── main.cj            // 入口

A/a1.cj 源码

package demo9.A// 包A中定义sealed接口
sealed interface Secret {func getSecret(): Unit //String
}

A/a2.cj 源码

package demo9.A// 同包内可实现
public class ASecret <: Secret {   public override func getSecret(): Unit {println("A的秘密") }
}

B/b1.cj 源码

// 包B中尝试实现(编译报错,故注释掉)
package demo9.B
import demo9.A.*// class BSecret <: Secret {  // 错误:sealed接口不允许跨包实现
//     public override func getSecret(): Unit {
//         println("B的秘密")   // return "B的秘密" 
//     }
// }

入口main.cj源码

package demo9import demo9.A.ASecret// 主函数
main() {let ok = ASecret()ok.getSecret()     // 正常输出: A的秘密
}

顺便提示:

若将此示例中函数的类型Unit改为String,将报错。原因是实现类重写接口方法时,返回类型必须与接口中定义的完全一致。

Unit 与 String 的区别:

  •  Unit 表示 “无返回值”(类似其他语言的 void),方法中可通过 println 输出内容,但无需 return。

  •  String 要求方法必须通过 return 语句返回一个字符串,否则会报错。

需要如下修改:

A/a1.cj 修正为:

package demo9.A// 接口方法返回String
sealed interface Secret {func getSecret(): String
}

A/a2.cj 修正为:

// 实现类方法也返回String,与接口匹配
public class ASecret <: Secret {   public override func getSecret(): String {return "A的秘密"  // 返回String,而非仅打印}
}

main.cj 修正为:

package demo9import demo9.A.ASecretmain() {let ok = ASecret()println(ok.getSecret())  // 输出: A的秘密(打印返回的String)
}

Any 类型

Any 类型是一个内置的接口(所有类型的隐式父接口),仓颉中所有接口都默认继承它,所有非接口类型都默认实现它,因此所有类型都可以作为 Any 类型的子类型使用。这意味着不需要程序员自己写interface Any {}。

目前Any类型,必须先通过模式匹配将其转换为具体类型,然后再打印。

注意,仓颉语言目前不能直接使用println(anyObj) 打印输出,因为对Any类型仓颉语言未提相关机制。例如:

main() {
    var any: Any = 1
    //pringln(any)  //行不通
    Any = 2.0
    //pringln(any)  //行不通
    Any = "hello, world!"
    //pringln(any)  //行不通
}


应写为(推荐方案)

func printAny(value: Any) {match (value) {case i: Int64 => println(i)case f: Float64 => println(f)case s: String => println(s)case b: Bool => println(b)case _ => println("unknown type")}
}main() {var any: Any = 1printAny(any)  // 输出: 1any = 2.0printAny(any)  // 输出: 2.000000any = "hello, world!"printAny(any)  // 输出: hello, world!
}

运行截图:

或写为:

func anyToString(value: Any): String {match (value) {case  i: Int64 => return i.toString()case  f: Float64 => return f.toString()case  s: String => return scase  b: Bool => return b.toString()case _ => return "unknown"}
}main() {var any: Any = 1println("Value: ${anyToString(any)}")  // 输出: Value: 1any = 2.0println("Value: ${anyToString(any)}")  // 输出: Value: 2.000000 any = "hello, world!"println("Value: ${anyToString(any)}")  // 输出: Value: hello, world!
}

关于Any类型(Any 接口)还可见https://blog.csdn.net/cnds123/article/details/150399926

http://www.dtcms.com/a/390121.html

相关文章:

  • 用 go-commons 打造一个轻量级内置监控系统,让服务开箱即用
  • PyQt6之QSpinBox计数器应用
  • 大模型应用开发4-MCP实战
  • Ruoyi-vue-plus-5.x第八篇文件管理与存储: 8.3 文件处理功能
  • 【51单片机】【protues仿真】基于51单片机PM2.5温湿度测量蓝牙系统
  • 病毒学原理
  • 怎样快速搭建一个高效的数据存储系统:Python实战指南
  • 音频驱动视频生成新突破:Wan2.2-S2V 模型全面体验与教程
  • 关于pc端分页+h5端加载更多的vue3简单钩子函数
  • MySQL 练习题
  • 推客小程序二级分销机制设计与实现:从0到1搭建裂变增长引擎
  • 【C++】多态(上)
  • uos中创建自定义Ip (192.168.137.1)的热点的方法
  • 【每日算法】搜索插入位置 LeetCode
  • vue+springboot+ngnix前后端分离项目部署
  • sward入门到实战(1) - 安装教程
  • 独立站的优势有哪些
  • Java学习历程18——哈希表的使用
  • 机械传动里的名词——传动比
  • qiankun 主子应用部署教程(Nginx 小白版)
  • 开启视觉奇旅:走进《计算机图形学》的世界
  • 光伏组件IV曲线测试仪的功能
  • MySQL MHA
  • 【试题】信息安全管理员考试题库
  • 硬件(十四)SPI通信协议
  • 大模型学习:使用FastText工具进行文本分类
  • pip 指令大全
  • 计算机基础·MySQL
  • 22-29、深度学习知识手册:从全连接到生成模型的融会贯通指南
  • 【FastCAEFlow案例分享】软件在汽车场景中的应用