← Back to lessons

32 Generic Classes

Intermediate

To create a generic class in Cangjie, place any number of type parameters after the class name in <>. Then you can use your type parameter throughout your class. If you want to introduce type constraints, place them after where. (T <: T means absolutely nothing - each type fulfills that.)

Because we do not know what type T will be, we do not know whether it has a default constructor or value, so we have to use an option for initialization of the array (we set a default value of None).

Parameter variable value, has type T.

Return of function remove is also T.

getOrThrow is a function that operates on Options, and allows us to extract value from inside an option, as long as its not None.

We can instantiate Queue for strings using this syntax.

Adding elements to the queue is straightforward

Removing elements is also simple. (keep in mind remove() returns T)

Instantiation for Int64s is the same as for strings, with a different type.

generic_classes.cj
class Queue<T> where T <: T {
    let MaxSize = 100
    let values: Array<?T>

    public Queue(var number_of_elements!: Int64 = 0,
                 var start!: Int64 = 0, var end!: Int64 = 0) {
        values = Array<?T>(MaxSize, item: None)
    }

    public func is_empty(): Bool {
        number_of_elements == 0
    }

    public func is_full(): Bool {
        number_of_elements == MaxSize
    }

    public func add(value: T) {
        if (is_full()) {
            throw Exception("Queue is full")
        }
        number_of_elements++
        values[start] = Some(value)
        start = (start + 1) % MaxSize
    }

    public func remove(): T {
        if (is_empty()) {
            throw Exception("Queue is empty")
        }
        number_of_elements--
        let temp = values[end].getOrThrow()
        end = (end + 1) % MaxSize
        temp
    }
}

main() {
    let StringQ = Queue<String>()
    let names = ["Isaac", "Ali", "Dan", "Max", "Sofia"]

    for (str in names) {
        StringQ.add(str)
    }

    while (StringQ.is_empty() == false) {
        print("${StringQ.remove()} ")
    }
    println()

    let IntQueue = Queue<Int64>()
    let numbers = [1, 69, 420, 2137, 3, 7, 17]

    for (number in numbers) {
        IntQueue.add(number)
    }

    while (IntQueue.is_empty() == false) {
        print("${IntQueue.remove()} ")
    }
    println()
}

// Output: 
// Isaac Ali Dan Max Sofia 
// 1 69 420 2137 3 7 17