DEV Community

SameX
SameX

Posted on

HarmonyOS Next multi-interface implementation in-depth practice: building a flexible and scalable type capability system

In HarmonyOS Next development, multi-interface implementation allows types to have multiple capabilities at the same time, and build a flexible type system by combining the behaviors of different interfaces.This article is based on the "Cangjie Programming Language Development Guide", which analyzes the syntax rules, application scenarios and collaborative strategies with class inheritance by multi-interface implementation.

1. Basic syntax and rules for multi-interface implementation

A type can implement multiple interfaces at the same time, using & to separate the interface list, and the syntax is as follows:

class Type <: Interface1 & Interface2 & Interface3 {
// Implement all interface members
}
Enter fullscreen mode Exit fullscreen mode

1. Merge implementation of interface members

When a type implements multiple interfaces, an implementation needs to be provided for members of each interface:

interface Printable { func print(): Unit }
interface Connectable { func connect(): Bool }

class Printer <: Printable & Connectable {
public func print() { println("Print document") }
    public func connect(): Bool { 
println("Connect the printer")
        return true 
    }
}
Enter fullscreen mode Exit fullscreen mode

2. Interface conflict handling

If multiple interfaces contain members of the same name, they need to be handled uniformly in the implementation:

interface A { func action(): Unit }
interface B { func action(): Unit }

class ConflictImpl <: A & B {
public func action() { // Unified implementation of the same name function
println("processing the action of interfaces A and B")
    }
}
Enter fullscreen mode Exit fullscreen mode

2. Application scenarios of interface combination

1. Multiple abstractions of device capabilities

IoT devices often need to have multiple capabilities (such as communication, storage, and display) at the same time, and implement them through multiple interfaces:

// Communication interface
interface Communicable {
    func send(data: String): Bool
    func receive(): String
}

// Storage interface
interface Storable {
    func save(data: String): Bool
    func load(): String
}

// Display interface
interface Displayable {
    func show(text: String): Unit
}

// Smart terminal devices implement all interfaces
class SmartTerminal <: Communicable & Storable & Displayable {
// Realize communication capabilities
public func send(data: String): Bool { /* Send logic */ }
public func receive(): String { /* Receive logic */ }

// Implement storage capabilities
public func save(data: String): Bool { /* Storage logic */ }
public func load(): String { /* Read logic */ }

// Implement display capability
    public func show(text: String): Unit { println(text) }
}
Enter fullscreen mode Exit fullscreen mode

2. Combination optimization of algorithm interfaces

By combining sorting and search interfaces, a multifunctional data structure is realized:

interface Sorter {
    func sort<T: Comparable>(array: [T]): [T]
}

interface Searcher {
    func search<T: Equatable>(array: [T], target: T): Int
}

class Utility <: Sorter & Searcher {
    public func sort<T: Comparable>(array: [T]): [T] { array.sorted() }
    public func search<T: Equatable>(array: [T], target: T): Int {
        array.firstIndex(of: target) ?? -1
    }
}
Enter fullscreen mode Exit fullscreen mode

3. Multi-interface matching in generic constraints

Generic function constrainable types must implement multiple interfaces to improve code reusability:

func processDevice<T: Communicable & Storable>(device: T) {
let data = "device data"
    device.send(data: data)
    device.save(data: data)
}

// Call example
let terminal = SmartTerminal()
processDevice(device: terminal) // Legal, SmartTerminal implements dual interfaces
Enter fullscreen mode Exit fullscreen mode

3. Collaborative strategies with class inheritance

1. A hybrid implementation of interfaces and abstract classes

Abstract classes can be used as base classes for multi-interface implementations, providing default implementations of some interfaces:

abstract class AbstractDevice <: Communicable {
public func send(data: String): Bool { /* general send logic */ }
public abstract func receive(): String // Abstract function, subclass implementation
}

class WirelessDevice <: AbstractDevice & Storable {
public func save(data: String): Bool { /* Implement storage interface */ }
public override func receive(): String { /* Implement abstract function */ }
}
Enter fullscreen mode Exit fullscreen mode

2. Interface priority principle: combination replacement inheritance

When types need to have multiple independent capabilities, interface combinations are preferred over multi-layer inheritance:

// Counterexample: Multi-layer inheritance leads to complexity
open class Animal { }
class FlyingAnimal <: Animal { } // Flying ability is inherited
class Bird <: FlyingAnimal { } // Birds inherit flight capabilities

// Formal example: interface combination implementation capability
interface Flyable { func fly(): Unit }
class Bird <: Animal, Flyable { 
public func fly() { /* Implement flight interface */ }
}
Enter fullscreen mode Exit fullscreen mode

3. Interface extension (Extend) and type adaptation

By extending the implementation of adding interfaces to existing types, no need to modify the original type:

interface Loggable { func log(message: String) }

// Extend Loggable interface for Int type
extend Int <: Loggable {
    public func log(message: String) {
        println("\(message): \(self)")
    }
}

// Use example
let number: Int = 42
number.log(message: "value") // Output: value: 42
Enter fullscreen mode Exit fullscreen mode

4. Limitations and best practices of multi-interface implementation

1. Interface order and readability

The interface list is sorted by capability importance, and the commonly used interface prefixes:

class Robot <: Activatable & Movable & Communicable { ... } // Core capability front-end
Enter fullscreen mode Exit fullscreen mode

2. Avoid excessive combination

Control the number of interfaces implemented by the type and keep the responsibilities single:

// Counterexample: Single type implements too many interfaces
class AllInOne <: A & B & C & D & E> { ... } // Difficult to maintain

// Positive example: Split into multiple focused interface types
class Core <: A & B> { ... }
class Extension <: C & D & E> { ... }
Enter fullscreen mode Exit fullscreen mode

3. Package visibility and export of interfaces

When using interfaces across packages, you need to ensure that both the interface and implementation classes are public and export correctly:

package devices  
public interface RemoteControllable { ... }  
public class SmartTV <: RemoteControllable { ... }  

// Other package references
import devices.*  
let tv: RemoteControllable = SmartTV() // Legal
Enter fullscreen mode Exit fullscreen mode

5. Summary: The architectural value of interface combination

HarmonyOS Next's multi-interface implementation mechanism provides the following advantages for type design:

  • Skill decoupling: Encapsulate different functions into independent interfaces, and types are combined on demand;
  • Flexible extension: Add functions to existing types by implementing new interfaces without modifying the original logic;
  • Generic Enhancement: Constrain multiple abilities in generic programming and improve the scope of code application.

Top comments (0)