文章

Go v.s. Java

接口:组合 vs 继承

  • Java:从抽象到具体(Top-Down)

    • Java 开发倾向于先设计抽象(接口、基类),再去实现它们。
    • 鼓励开发者先思考如何构建通用的核心功能,基于核心功能通过继承构建其他功能。
    • Java 使用 implement 关键字实现接口。
    1
    2
    3
    4
    5
    6
    7
    
    interface Animal {
        void speak();
    }
    
    class Dog implements Animal {
        public void speak() { System.out.println("Woof"); }
    }
    

    你一开始就得知道你需要什么“动物接口”,再去设计 Dog。

  • Go:从具体到抽象(Bottom-Up)

    • Go 倾向于先实现具体类型和方法,然后在具体使用场景中提炼出接口
    • 鼓励开发者进行”行为驱动的面向对象开发”,先专注于用代码解决问题,在此过程中进行抽象。
    • Go 使用的是“结构化相等”——如果这两个东西的形状相同,它们就可以相互替换。因此只需实现接口的所有方法,就视为实现了此接口。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    
    type Dog struct{}
    
    func (d Dog) Speak() {
        fmt.Println("Woof")
    }
    
    // Somewhere else:
    type Speaker interface {
        Speak()
    }
    
    func MakeItSpeak(s Speaker) {
        s.Speak()
    }
    
    MakeItSpeak(Dog{}) // Dog 自动实现 Speaker
    

    Dog 并不知道 Speaker 存在,但因为方法匹配,自动就“被认为”实现了接口。

虽然 implements 对熟悉静态类型系统的程序员来说很合理,但它会在接口声明和实现之间创建时间依赖关系,也就是说,接口声明必须先于实现出现,这一点制造了代码耦合、演进困难、先后依赖等问题。现代语言 GoTypeScript 已经意识并改进了这一点。

类型断言 vs 隐式类型转换

interface{} vs Object

本文由作者按照 CC BY 4.0 进行授权

© . 保留部分权利。

本站采用 Jekyll 主题 Chirpy