赞
踩
如果您是 Java 开发人员,您会发现 Rust 相对容易掌握,这要归功于这两种语言的相似性。
根据Stack Overflow 的调查,Rust 已经在语言流行度或最常用语言的阶梯上攀升,但最引人注目的是,Rust 不断成为“最受喜爱的语言” 。这证明了使用 Rust 的丰富经验。
Rust 语法
像 Java 一样,Rust 也是编译好的。它被编译为 LLVM 规范,在精神上类似于 JVM ,允许输出到各种目标平台。
和 Java 一样,Rust 起源于 C 血统。它在块中使用花括号,在行终止时使用分号,这与 Java 完全相同。例如,您可以 在这里 看到一个简单的程序,如:
fn main () { println !( <font>"Hello, InfoWorld!"</font><font> ); } </font>
请注意,有一个main()函数,类似于 Java 中的main函数入口点。
Rust中的函数
函数在Rust中是独立的,它们可以在任何地方声明,包括嵌套在其他函数中。
这与Java不同,在Java中,函数总是被声明为对象的方法(除了lambdas的情况)。
换句话说,在Java中,所有东西都是一个对象。在Rust中则不然。
fn main() { println!(<font>"Hello, world!"</font><font>); fn function2(){ println!(</font><font>"Hello InfoWorld"</font><font>); } function2(); function3(); } fn function3() { println!(</font><font>"Hello again."</font><font>); } </font>
隐式返回值
与Java不同,Rust允许你在函数的结尾跳过返回return关键字。函数中的最后一条语句将自动被评估为返回值。
这样做时,你可以省略最后语句中的分号。
lambdas代码
和Java一样,Rust支持功能式编码的lambdas。语法是不同的,但如果你熟悉Java流API,就不难理解。
项目显示了使用map()函数使一组字符串大写的情况。正如你所看到的,这与Java很相似。
<font><i>// Rust</i></font><font> fn main() { let animals = [</font><font>"dog"</font><font>, </font><font>"badger"</font><font>, </font><font>"quokka"</font><font>]; let result = animals.iter().map(|value| value.to_uppercase()); <b>for</b> animal in result { println!(</font><font>"Uppercased: {}"</font><font>, animal); } } </font>
map()函数需要一个两部分的参数:
注意,像Java一样,Rust的lambdas是捕获周围块的状态的闭包。
换句话说,它们可以访问它们所执行的变量上下文。
对象是Rust中的struct
下面代码介绍了struct关键字。struct是结构的简称,它允许你定义一个数据容器,就像Java中类的状态部分。
struct Animal { name: String } fn main() { let dog = Animal{ name: String::from(<font>"Shiba"</font><font>) }; println!(</font><font>"{}"</font><font>, dog.name); } </font>
你在struct的大括号内定义结构的成员。这些变量类似于公共成员。
请注意,在你声明dog变量的那一行,没有必要调用new关键字。
Rust可以从上下文中推断出,但是一个新的引用变量名是有必要的。
接下来,注意到变量名在创建时被设置为一个带值的字符串。这是通过调用内置的String.from方法,使用双冒号引用操作符完成的。
最后,注意到就像Java一样,Rust使用点运算符来访问dog实例的名字字段:dog.name。
方法
您可以向struct添加函数,这些函数的行为方式与Java中的方法基本相同。
例如,为了给上述代码中所示的Animal struct添加一个speak()方法,你可以使用impl关键字。
impl Animal { fn speak(&self) { println!(<font>"{}"</font><font>, self.name); } } </font>
Impl意味着实现接口或父类。
上述代码我们正在实现Animal struct:我们定义了一个方法speak,它需要一个参数。
这个参数是特殊的&self指针(Rust中的&意味着参数是一个引用指针)。
这个特殊指针的语义与Java中的this关键字非常相似。它指的是当前活动的对象实例。
调用dog.speak()将输出当前实例化对象的名称。
在这个例子中输出结果是 "Shiba"。
Rust中的可变性
如果你有Java背景,那么Rust的一个比较奇怪的地方就是变量的默认不可变性。
简而言之,当你在Rust中声明一个变量时,它默认是不可变的,试图改变它将导致一个错误。
要使一个变量可变,必须添加mut关键字,但mut一次只能由一个引用添加。
记住,Rust高度关注保持代码的线程安全。这也避免了在Java中看到的并发修改错误。
下面代码显示了如何使dog对象变异,然后给它分配一个新的名字。
let mut dog = Animal{ name: String::from(<font>"Shiba"</font><font>) }; dog.name = String::from(</font><font>"Suki"</font><font>); println!(</font><font>"{}"</font><font>, dog.name); </font>
Rust中的类型推理
在Rust中,你并不总是需要告诉编译器你正在声明什么类型的变量。
对于来自Java的开发者来说,这似乎很奇怪,因为在Java中没有推断变量类型的工具。
例如,下面代码编译器正确地将类型推断为整数。
let number1 = 10; let number2 = 10; println!(<font>"{}"</font><font>, number1 * number2); </font>
阴影Shadowing和变量名
另一个可能会让Java开发者感到惊讶的Rust特性是所谓的变量阴影shadowing。
从本质上讲,你可以在一个变量上面创建一个同名的可变变量“罩子”,而不是把它声明为可变的。
这是一种一次性的可变性,为相同的变量名称创建一个新的空间。
一般来说,重复使用同一变量名的能力与Java不同。
下面显示了一个变量阴影的简单例子。
fn main() { let x = 5; let x = x + 1; println!(<font>"The value of x is: {}"</font><font>, x); </font><font><i>// outputs 6</i></font><font> } </font>
Rust中的元组类型
Rust支持元组类型,它是一种复合变量,在Java中没有真正的类似物。
下面代码向你展示了一个元组的实例。
fn main() { let myTuple = (<font>"Sum"</font><font>, 10, 5); let (x, y) = myTuple ; println!(</font><font>"The {} is: {}"</font><font>, x, y + z); } </font>
在这里你可以看到myTuple变量是用括号声明的,包含三个值、一个字符串和两个整数。这就是一个元组。
你可以将元组 "去结构化(解构或析构) "为元组变量,就像在上面代码中看到的那样,let关键字被用来用元组中的值填充每个变量x、y和z。
你也可以通过索引访问元组成员。例如,tup.0引用元组的第一个字段(字符串 "Sum")。
Rust中的traits和泛型
在Rust中,有一个traits的概念,它类似于Java中的“接口interface”。它们定义了一个类型与其他类型共享的属性。
换句话说,traits抽象了不同类型的共同功能。
Rust中的泛型与Java中的泛型类似,使用类似的角括号语法,根据类型的共享属性,以一般的方式处理类型。
pub trait Summary { fn summarize(&self) -> String; } pub struct NewsArticle { pub headline: String, pub location: String, pub author: String, pub content: String, } impl Summary <b>for</b> NewsArticle { fn summarize(&self) -> String { format!(<font>"{}, by {} ({})"</font><font>, self.headline, self.author, self.location) } } pub struct Tweet { pub username: String, pub content: String, pub reply: bool, pub retweet: bool, } impl Summary <b>for</b> Tweet { fn summarize(&self) -> String { format!(</font><font>"{}: {}"</font><font>, self.username, self.content) } } fn main() { let tweet = Tweet { username: String::from(</font><font>"dog_post"</font><font>), content: String::from(</font><font>"A Shih Tzu is smaller than a Lurcher"</font><font>, ), reply: false, retweet: false, }; println!(</font><font>"1 new tweet: {}"</font><font>, tweet.summarize()); } </font>
在这里,trait关键字被用来定义一个Summary属性,然后用impl关键字为每个struct对象类型(NewsArticle和Tweet)实现这个属性。
所以这与Java中的接口非常相似,只是在Java中,接口定义了整个类的表面,而不是零散地定义方法。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。