我提供了埃文·卡梅隆(Evan Cameron)的一篇文章的译文,该文章可以帮助Java开发人员更好地理解这两种语言之间的差异和相似之处- 原始语言位于作者的网站上。如果不考虑自己是一名经验丰富的Rust开发人员,我不太可能能够合理地参与可能的讨论。
我想对博客进行更改,并留下更多敏感主题来关注它们。在Rust社区中可以做的最重要的主题之一就是对新开发人员的培训。我一直在为那些习惯于使用Java并帮助掌握新项目语言的人考虑最好的方法来教授Rust。
Java是我在大学学习的一种语言,因此我的使用经验有些过时,并且我还没有进行任何实际的尝试来跟上该语言。我上次写Java时,如果要传递函数作为参数,则必须声明一个新接口或将该函数包装在中Callable<T>。从那时起,Java已经走了很长一段路。这些是添加的功能,这些功能可以从功能编程中获得明显的效果。我说的是lambda,Optional类型等。本文不会讨论如何用Rust编写代码,或者您需要丢弃所有Java代码。Java是具有实际用例的出色语言。我想对初学者Rust程序员进行Java和Rust的比较。
语言动机
首先介绍每种语言的目标。创建Java是为了解决许多问题。它必须“简单,面向对象和模块化”,必须在虚拟机中运行,可移植到不同的体系结构,并且必须具有高性能。 Rust的目标是“速度更快,内存效率更高”,“类型系统丰富,内存安全,线程安全”,生成良好的错误消息以及内置的包管理器。
它们之间有一些区别。 Rust的性能很高,提到缺少运行时环境,内存安全性以及强大的类型系统。这些是Rust真正发挥作用的地方;其代码高效且安全。需要每秒处理成千上万个请求的服务器,需要快速运行并使用少量内存,可在嵌入式设备上运行的OS(操作系统)或代码的应用程序。这些事情可以用其他语言完成,但这就是Rust所创建的领域。 Rust允许这样做,同时防止诸如缓冲区溢出,悬空或空指针之类的事情。
, Rust ( wasm frontends yew ). , , , , ( ) . .
, , Java Rust :
; , , . , .
Rust . Rust enum struct. enum — ( , ). enum Java, , Java enum, . enum , , . , , Rust null nil. Rust, .
enum Option<T> {
None,
Some(T),
}
Option, T. T , T. Option 2 , None (" ") , Some T. :
let a = Some("foo".to_string());
let b: Option<usize> = Some(1);
. , . , . , .
Rust enum match. , .
fn plus(a: Option<usize>) -> Option<usize> {
match a {
Some(v) => Some(v + 1),
None => None
}
}
, . match. cheats.rs match. if/else.
Option, - ( Some ) . , Option , .
fn plus(a: Option<usize>) -> Option<usize> {
a.map(|v| v + 1)
}
|| {} — . Rust - , , " " .
struct — . , , , .
struct A {
field: usize
}
"" .
let a: (usize, usize) = (1, 1);
.
struct Foo<T> {
field: T
}
enum struct . , impl . , Rust. struct impl , :
struct Thangs {
list: Vec<Thang>
}
struct Thang;
impl Thangs {
fn new() -> Self {
Self {
list: vec![]
}
}
fn add_thang(&mut self, thang: Thang) {
self.list.push(thang);
}
}
fn main() {
let mut thangs = Thangs::new();
thangs.add_thang(Thang);
}
Java, value.method() " ". , &mut self :
let mut thangs = Thangs::new();
Thangs::add_thang(&mut thangs, Thang);
, Rust . enum struct . Java - struct impl , "", ( , ). " Rust ", Java , . Java 14 "Records" () . , Java "", ( , Rust , sum product ). Java, - , , !
Rust . , . . :
struct Thing { field: usize }
fn main() {
let a = Thing { field: 1 };
}
- . , , Sized. , . , ( main) .
Java, new, , .
Box ( stdlib , Rc, Arc ..). , , ? , , , , ( ). , , , , "" Box , .
fn main () {
let a = Box::new(Thing { field: 1 });
}
, . , . , , a a. usize , .
Box . - Java,
trait Foo {}
struct Thing;
impl Foo for Thing {}
struct OtherThing;
impl Foo for OtherThing {}
fn main () {
let a: Vec<Box<dyn Foo>> = vec![Box::new(OtherThing), Box::new(Thing)];
}
trait, . , . , . Rust , , , , .
, , . Rust — .
.
enum List<T> {
Nil,
Cons((T, List<T>))
}
. List<T> Nil , Cons, . , , ?
?
error[E0072]: recursive type `List` has infinite size
--> src/lib.rs:7:1
|
7 | enum List<T> {
| ^^^^^^^^^^^^ recursive type has infinite size
8 | Nil,
9 | Cons((T, List<T>))
| ------------ recursive without indirection
|
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `List` representable
. help . , , . , , , N-? , , ? , . .
, .
enum List<T> {
Nil,
Cons((T, Box<List<T>>))
}
. , . .
Java Rust, ( ) :
enum Shape {
Circle { radius: f32 },
Rectangle { width: f32, height: f32 },
}
area () , , , :
impl Shape {
pub fn area(self) -> f32 {
match self {
Shape::Circle { radius } => std::f32::consts::PI * radius.powi(2),
Shape::Rectangle { width, height } => width * height,
}
}
}
Java . Rust pub ( ), ( ). , Rust reference.
. Java Shape Circle Rectangle, area. Rust Java, :
Shape:
- Java:
Shape - Rust:
Shape , ( match , )
Shape:
- Java: ""
Shape, , - Rust:
impl
' ' (expression problem). . enum Rust / Java. , Rust match enum. : « , ?»
, .
trait Area {
fn area(self) -> f32;
}
struct Rectangle {
width: f32,
height: f32
}
struct Circle {
radius: f32
}
impl Area for Rectangle {
fn area(self) -> f32 {
self.width * self.height
}
}
impl Area for Circle {
fn area(self) -> f32 {
std::f32::consts::PI * self.radius.powi(2)
}
}
, Circle Rectangle, perimeter, :
trait Perimeter {
fn perimeter(self) -> f32;
}
impl Perimeter for Rectangle {
fn perimeter(self) -> f32 {
2. * (self.width + self.height)
}
}
. , , "" " ".
fn do_something<T: Perimeter + Area>(shape: T) {
unimplemented!()
}
Rust . , , Java. , . Java , Rust . , . , , . Future , Iterator IntoIterator for..in, Index [], Add, Sub, Mul . , Add
Add std.
pub trait Add<Rhs = Self> {
type Output;
fn add(self, rhs: Rhs) -> Self::Output;
}
Std Add Rhs, Self, .. (1). « » Output (2) add, self ( self) rhs Rhs ( ) , Output (3).
use std::ops::Add;
#[derive(Debug)]
struct Content<T> {
val: T,
}
impl<T> Add for Content<T>
where
T: Add,
{
type Output = Content<<T as Add>::Output>;
fn add(self, rhs: Content<T>) -> Self::Output {
Content {
val: self.val + rhs.val,
}
}
}
fn main() {
let a = Content { val: 2 };
let b = Content { val: 5 };
println!("{:?}", a + b);
}
Content, T (1). Add , Content Add (2), , Content Add (3). , Output Content Output T, Add (4). , , , . , , . , " " , Rust. , Rust , ( ), .
, Sized , fn foo<T>(t: T) -> T, T: Sized. T: ?Sized, T . .
Java . OO Rust, Java. Java — (subtype polymorphism), Rust — (ad-hoc) . , , , ( <T: Trait> ).
, "" . , enum struct, impl. impl , . , , -. .
Rust . str, String, OsStr, OsString, CString CStr ( - ?). , str String, — . , , ?
&str , &str &String , String Deref<Target=str> ( Target= , Target " "). .
fn foo<S: AsRef<str>>(s: S) {
unimplemented!()
}
AsRef — stdlib. :
trait AsRef<T>
where
T: ?Sized,
{
fn as_ref(&self) -> &T;
}
, T, , &T. foo String,
let a = String::from("stuff");
foo(a);
? , ( ). Rust stdlib.
, . , , . , . Java ( , Java ). Java , . « ». Rust , .
, , . , - . , , . Rust , ! , Rust .
.
: Java Rust
Java , . , . - Java , .. . , , Java , ( Java <T> <T extends Class> ), Java , (type erasure). , Object -. Java, , — . - vtable, .
Rust . foo foo , foo . , foo 4 AsRef<str>, 4 . «». , Rust " ". ( Box), Object或转移虚拟表(如果我们不想要的话)。应该注意的是,这种方法的缺点是最终的代码大小和编译时间。取决于我们功能的多少个不同变体以及我们需要生成多少个实现,更多的代码必须通过LLVM,这会增加编译时间并增加实际生成的代码量。
联系人Evan Cameron:邮件,github,twitter,linkedIn
在Rust翻译的电报聊天中,对Rust翻译的讨论很慢。