Go 模拟实现 Java 接口中的默认方法

627 阅读1分钟

首先我们来看看 Java 中的Iterator接口,源码如下,它提供了removeforEachRemaining两个默认方法实现。如果在 Go 语言中,该如何实现这样的结构呢?

public interface Iterator<E> {
    boolean hasNext();

    E next();

    default void remove() {
        throw new UnsupportedOperationException("remove");
    }

    default void forEachRemaining(Consumer<? super E> action) {
        Objects.requireNonNull(action);
        while (hasNext())
            action.accept(next());
    }
}

话不多说,直接撸代码......

首先定义一个Iterator接口,代码如下:

type Iterator interface {
	HasNext() bool
	Next() any
	Remove()
	ForEachRemaining(action func(value any))
}

然后我们需要定义一个结构体,该结构体是Iterator接口的实现类型,代码如下:

注意观察AbstractIterator类型的代码结构。

type AbstractIterator struct {
	Iterator // 嵌入接口
}

func (this AbstractIterator) Remove() {
	panic("unsupported remove operation")
}

func (this AbstractIterator) ForEachRemaining(action function.Predicate) {
	for this.Iterator.HasNext() {
		if !action(this.Iterator.Next()) {
			return
		}
	}
}

AbstractIterator类型中我们实现了Iterator 接口 RemoveForEachRemaining 方法提供默认实现逻辑。

这样一来,当我们要实现Iterator接口时,可以直接将AbstractIterator类型嵌入自定义的结构体中,如下所示:

type Itr struct {
	AbstractIterator
    ......
}

那么,如何引用默认实现方法呢?

现在我们要用Itr类型实例引用ForEachRemaining方法,那么我们只需要将Itr实例作为参数,为其嵌入字段AbstractIterator初始化即可。

// 实例化 Itr 对象
itr := &Itr{}
// 初始化 AbstractIterator 属性, 避免间接调用 ForEachRemaining 方法时引发空指针错误
itr.AbstractIterator = AbstractIterator{Iterator: itr}
// 相当于 itr.AbstractIterator.ForEachRemaining
itr.ForEachRemaining(func(value any){
    fmt.Println(value)
})