为了账号安全,请及时绑定邮箱和手机立即绑定

您可以防止创建无效的自定义类型吗?

您可以防止创建无效的自定义类型吗?

Go
交互式爱情 2023-07-17 17:55:33
假设我们想要创建一个自定义Probability类型来表示 0 到 1 之间的数字。我们可以这样做:type Probability float64func NewProbability(p float64) (*Probability, error) {    if p < 0 || p > 1 {        return nil, errors.New("Invalid Probability")    }    tmp := Probability(p)    return &tmp, nil}只要我们的代码的客户端始终使用我们的NewProbability构造函数,这种方法就有效。但他们可以通过类型转换来绕过它:func main() {    // works as intended    p1, _ := NewProbability(0.5)    fmt.Println(*p1)    // errors as intended    _, err := NewProbability(2)    fmt.Println(err)    // circumvents our constraints...    // creates invalid Probability    p3 := Probability(2)    fmt.Println(p3)}https://play.golang.org/p/xJZQhkZLi_H2个问题:有没有什么方法可以防止这种规避,这样即使有的话Probability它也总是有效的?与主要问题无关:如果我tmp在构造函数中省略变量而是这样做return &Probability(p), nil,则会收到错误cannot take the address of Probability(p)(尝试一下)。为什么使用变量时tmp不会出现此错误?
查看完整描述

3 回答

?
MMTTMM

TA贡献1869条经验 获得超4个赞

您可以防止创建无效的自定义类型吗?

不。

“经典”OOP 语言所提倡的“如果防止误用就不会出现问题”的想法是没有根据的。如果用户不阅读您的文档就会出现问题。



查看完整回答
反对 回复 2023-07-17
?
湖上湖

TA贡献2003条经验 获得超2个赞

1)您可以尝试将 Probability 设为一个包含隐藏浮点值的结构,但您将无法将其用作数字。另一种选择是将 IsValid() 方法添加到 Probability(有点类似于 NaN)。

2) Probability(p) 是 p 的副本,类型为 Probability。它是一个运算结果的值,在分配给变量之前没有地址。当您将其分配给变量时,您可以获得该变量的地址。



查看完整回答
反对 回复 2023-07-17
?
慕桂英546537

TA贡献1848条经验 获得超10个赞

这个问题每隔一段时间就会出现一次。“确保”不会将无效值分配给某些自定义类型的唯一方法是在未导出的结构体字段中使用 getter 和 setter 来保护它:


type Probability struct {

    p float64

}


func NewProbability(p float64) (Probability, error) {

    if p < 0 || p > 1 {

        return Probability{}, errors.New("invalid probability")

    }

    return Probability{p}

}

对于像浮动这样简单的东西来说,这可能有点过分了。更明智的方法通常是检查每当您接受这样的参数时是否收到有效的概率:


func DidItHappen(p probability) (bool, error) {

    if p < 0 || p > 1 {

        return false, errors.New("invalid probability")

    }

    if /* roll the dice */ {

        return true, nil

    }

    return false, nil

}


查看完整回答
反对 回复 2023-07-17
  • 3 回答
  • 0 关注
  • 91 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信