我提供了埃文·卡梅隆(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翻译的讨论很慢。