适用于Java开发人员的Rust

我提供了埃文·卡梅隆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 :


  • ( GC)
  • ()

; , , . , .




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()); //    Option<String>

let b: Option<usize> = Some(1); //    Option<usize>,    

. , . , . , .


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 {
   // **  `new`    ,   ' '
   fn new() -> Self {
       Self {
           list: vec![]
       }
   }

   fn add_thang(&mut self, thang: Thang) {
       self.list.push(thang);
   }
}

fn main() {
  // ** &mut self   'add_thangs'   mut   
   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 };
    // .. do stuff with a
}

- . , , 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)]; //   
    //  ''     ,    
    //            Foo
    }

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; //          ( i32)
}

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) { //   ,    Perimeter  Area
        unimplemented!() // :   
        //        
    }


Rust . , , Java. , . Java , Rust . , . , , . Future , Iterator IntoIterator for..in, Index [], Add, Sub, Mul . , Add


Add std.


pub trait Add<Rhs = Self> { // 1
    type Output; // 2
    fn add(self, rhs: Rhs) -> Self::Output; // 3
}

Std Add Rhs, Self, .. (1). « » Output (2) add, self ( self) rhs Rhs ( ) , Output (3).


use std::ops::Add;

#[derive(Debug)]
struct Content<T> { // 1
    val: T,
}

impl<T> Add for Content<T> // 2
   where
    T: Add, // 3
{
    type Output = Content<<T as Add>::Output>; // 4
    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 { val: 7 }
}

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!()
}

AsRefstdlib. :


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:邮件githubtwitterlinkedIn


Rust翻译电报聊天中,对Rust翻译的讨论很慢


All Articles