Rust中::和.的区别是什么?

30

我对::.之间的区别感到困惑。它们看起来很相似,除了语法不同。

let mut guess = String::new();

io::stdin().read_line(&mut guess)
    .expect("Failed to read line");

《Rust编程语言》中的“编写猜数字游戏”

在上述情况下,我访问了String中的new()函数。那么String::new()String.new()之间有什么区别?.只用于方法吗?

3个回答

40

.用于左侧有值的情况,::用于类型或模块的情况。

或者说:.用于访问值成员,::用于访问命名空间成员。


1
我可以假设使用String::new()只是在访问该命名空间的成员。在io::stdin().read_line(&mut guess)的情况下,stdin()io的一个成员,但返回的值不是任何namespace的一部分,它只是一个实例(文档中说pub struct Stdin)?所以这是一个结构体?就像一个对象? - Dan
3
String 是一个结构体,new 是一个静态方法(没有 self 作为第一个参数),因此您可以通过 :: 访问它。io 是一个命名空间,您可以通过 :: 访问其中的内部 "things"(结构体、特性等)。 - hellow
2
@Dan:我不确定你在问什么。String::new()调用的是由String类型定义的函数。这与调用任何其他函数没有区别。io::stdin()返回一个值,因此.read_line查找并调用由Stdin类型定义的方法read_line。唯一不同的是,在.左侧的东西(Stdin)作为self参数传递给了read_line。而“对象”是如此地多重载,以至于我无法真正回答。这取决于您对“对象”的理解。 - DK.
这可能是我困惑的根源。什么使某个东西成为类型或模块?对于 pub fn stdin() -> Stdin,文档说明构造了一个 新句柄,其中 StdinStruct std::io::Stdin。它们似乎不被称为类型或模块。 - Dan
1
@Dan:这有点像问“什么使得某个东西成为结构体或函数?”;它们之所以是它们,是因为它们被定义为这样。我不知道还有什么可以告诉你的了。我感觉你可能没有理解到一些基本的东西,但我不确定是什么。在stdin的情况下,它没有指定结果是类型还是模块,因为它必须是一个类型,因为你不能返回一个模块。模块纯粹是用来组织事物的。 - DK.
2
从C#转向Rust,这个工作几乎类似于实例成员和静态成员,“.”表示调用类型的实例成员,“::”就像访问类型的静态成员。Rust中类型的实例方法看起来类似于C#中的扩展方法“public static void Foo(this MyType myType)”,而在Rust中则是“fn foo(&self)”。如果我错了,请纠正我,但是我认为这种类比可以帮助像我这样第一次尝试Rust的C#开发人员。 - Thadeu Fernandes

19
我发现在::.之间有一个有用的区别,这个区别在方法语法(Method Syntax)中有所展示。
当调用struct中的一个fn实例时,使用点号.:
struct Rectangle {
    width: u32,
    height: u32,
}

impl Rectangle {
    fn area(&self) -> u32 {
        self.width * self.height
    }
}

fn main() {
    let rect1 = Rectangle {
        width: 30,
        height: 50,
    };

    println!(
        "The area of the rectangle is {} square pixels.",
        rect1.area()
    );
}

另一方面,相关函数是不以self作为参数的函数。它们没有struct的实例:

impl Rectangle {
    // Associated Function
    fn square(size: u32) -> Rectangle {
        Rectangle {
            width: size,
            height: size,
        }
    }
}

:: 用于调用这些函数。

fn main() {
    let sq = Rectangle::square(3);
}

相比之下,.用于返回一个方法(结构体实例的函数)。


酷,解释一下,“::”用于静态方法、命名空间变量。而“.”用于成员(实例)。简而言之。 - Arnab Mukherjee

0

我喜欢这样思考,如果方法将&self作为参数,我们使用.语法;如果不需要&self作为参数,我们使用::语法。

例如,引用@Dan的回答来计算面积时,我们需要一个对象,它的lengthheight。所以我们将&self作为参数传递,并使用.语法。创建一个新的正方形时,我们不需要现有对象,因此使用::语法。

x.do()表示在对象x上执行函数do(),而x::do()表示从x的命名空间中执行函数do()

严格来说,.用于结构体的方法,::用于结构体关联函数。


虽然这是正确的,但这并不能解释所有使用::的情况。它还用于访问模块成员。被接受的答案解释得很好。 - Chayim Friedman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接