如何调用实现接口的结构的特定方法

How to call specific method of struct that implements an interface

我有以下接口和一些实现它的结构:

package main

import "fmt"

type vehicle interface {
    vehicleType() string
    numberOfWheels() int
    EngineType() string
}

// -------------------------------------------

type truck struct {
    loadCapacity int
}

func (t truck) vehicleType() string {
    return "Truck"
}

func (t truck) numberOfWheels() int {
    return 6
}

func (t truck) EngineType() string {
    return "Gasoline"
}

// -------------------------------------------
type ev struct {
    capacityInKWh int
}

func (e ev) vehicleType() string {
    return "Electric Vehicle"
}

func (e ev) numberOfWheels() int {
    return 4
}

func (e ev) EngineType() string {
    return "Electric"
}

func (e ev) Capacity() int {
    return e.capacityInKWh
}

// -------------------------------------------

type dealer struct{}

func (d dealer) sell(automobile vehicle) {
    fmt.Println("Selling a vehicle with the following properties")
    fmt.Printf("Vehicle Type: %s \n", automobile.vehicleType())
    fmt.Printf("Vehicle Number of wheels: %d \n", automobile.numberOfWheels())
    fmt.Printf("Vehicle Engine Type: %s \n", automobile.EngineType())

    if automobile.EngineType() == "Electric" {
        fmt.Printf("The battery capacity of the vehicle is %d KWh", automobile.Capacity())
        //fmt.Printf("Here")
    }
}

func main() {

    volvoTruck := truck{
        loadCapacity: 10,
    }

    tesla := ev{
        capacityInKWh: 100,
    }

    myDealer := dealer{}
    myDealer.sell(volvoTruck)
    fmt.Println("---------------------------")
    myDealer.sell(tesla)

}
我的 dealer{} 结构中的

Sell 方法接收一个接口。在这个方法中,我想调用一个只存在于实现该接口的结构之一而不存在于其他结构中的方法:

if automobile.EngineType() == "Electric" {
            fmt.Printf("The battery capacity of the vehicle is %d KWh", automobile.Capacity())
        }

请注意 Capacity() 仅存在于 ev{} 中,而不存在于 truck{} 中。有没有办法做到这一点,而不必将此方法添加到接口强制所有实现都使用它?

您可以使用 type assertion 检查方法是否存在。检查该值(或更具体地说,它的类型)是否有您正在寻找的方法,如果有,您可以调用它。

可以通过检查该值是否使用该单一方法实现接口来实现对方法的检查:

if hc, ok := automobile.(interface {
    Capacity() int
}); ok {
    fmt.Printf("The battery capacity of the vehicle is %d KWh", hc.Capacity())
}

然后输出将是(在Go Playground上试试):

Selling a vehicle with the following properties
Vehicle Type: Truck 
Vehicle Number of wheels: 6 
Vehicle Engine Type: Gasoline 
---------------------------
Selling a vehicle with the following properties
Vehicle Type: Electric Vehicle 
Vehicle Number of wheels: 4 
Vehicle Engine Type: Electric 
The battery capacity of the vehicle is 100 KWh

如果你为它创建一个命名接口类型就更好了:

type HasCapacity interface {
    Capacity() int
}

然后:

if hc, ok := automobile.(HasCapacity); ok {
    fmt.Printf("The battery capacity of the vehicle is %d KWh", hc.Capacity())
}

输出是一样的,在 Go Playground 上试试这个。