2014-11-15 4 views
0

ржавчина не имеет встроенного Object тип я принимаю его? Если да, то как я, скажем, создать HashMap из «нечто», что в Java будет Object:A встроенный объект в ржавчине

fn method1(my_hash_map: HashMap<&str, ???>) { ... } // Rust 
    void method1(Map<String, Object> myMap) { ... } // Java 
+2

Вы ищете [ 'any'] (http://doc.rust-lang.org/core/any/). – rightfold

ответ

4

Если вы хотите HashMap, которые могут смешиваться значения многих различных типов, вы должны использовать Any. Наиболее прямым эквивалентом Map<String, Object> будет HashMap<String, Box<Any>>. Я переключил &str на String, потому что &str без срока службы, вероятно, не то, что вы хотите, и в любом случае даже удалено с Java String, чем у Rust's String.

Однако, если вы просто не заботятся о типе значений, это проще и эффективнее сделать method1 родовое:

fn method1<T>(my_hash_map: HashMap<String, T>) { ... } 

Конечно, вы также можете добавить ограничения T:Trait сделать более интересные вещи со значениями (см. Object позволяет сравнивать равенство и хеширование).

+0

Почему 'Box ', а не только 'Any'? –

+3

@AlexanderSupertramp 'Any' - это черта, а не конкретный тип. Он не имеет известного размера, поэтому вы не можете хранить его по значению, как по умолчанию для типов. Это также относится к Java, но не имеет значения, потому что все объекты доступны через ссылки/указатели в любом случае.В Rust существует несколько видов указателей, поэтому вам нужно решить, что вы хотите использовать: есть также '& 'a Any', и вскоре-ish' Rc ',' Arc 'и т. Д. – delnan

1

Чтобы развернуть на комментарий rightføld, в Any ближайший вы можете реально получить в Русте, хотя делает пришел с основным ограничением: это только реализуется по типам, которые удовлетворяют 'static срок службы; то есть вы не можете обращаться с любым типом, который содержит нестатические ссылки, как Any.

Второе осложнение состоит в том, что Object в Java имеет ссылочную семантику и дает вам общую собственность. Таким образом, вам нужно что-то вроде Rc<RefCell<Any>>, чтобы получить что-то примерно сопоставимое. Обратите внимание, однако, что это сильно обескуражен, поскольку он в основном перемещает множество проверок во время выполнения. Что-то вроде этого должно быть последствием последней инстанции.

Наконец, следует отметить, что, насколько мне известно, нет никакого способа, чтобы сделать динамическую вентиляционное на качестве Any ни к чему другим чем стертый типа; поэтому вы не можете взять ссылку на значение, которое, скажем, реализует Show, превратите его в &Any, а затем повысите до &Show.

Более эффективные альтернативы, если применимо, включают обобщение типа значения (так что используйте общие функции и структуры), используя enum, если существует фиксированный конечный список типов, которые вы хотите поддерживать, или писать и реализовывать пользовательский признак, в этой последовательности.

Чтобы дать вам пример работы с Any, однако, я бросил следующее вместе. Обратите внимание, что мы должны попытаться явно повысить эффективность каждого поддерживаемого типа.

#![feature(if_let)] 

use std::any::{Any, AnyRefExt}; 
use std::collections::HashMap; 

fn main() { 
    let val_a = box "blah"; 
    let val_b = box 42u; 
    let val_c = box 3.14159f64; 

    let mut map = HashMap::new(); 
    map.insert("a".into_string(), val_a as Box<Any>); 
    map.insert("b".into_string(), val_b as Box<Any>); 
    map.insert("c".into_string(), val_c as Box<Any>); 

    println!("{}", map); 
    splang(&map); 
} 

fn splang(map: &HashMap<String, Box<Any>>) { 
    for (k, v) in map.iter() { 
     if let Some(v) = v.downcast_ref::<&str>() { 
      println!("[\"{}\"]: &str = \"{}\"", k, *v); 
     } else if let Some(v) = v.downcast_ref::<uint>() { 
      println!("[\"{}\"]: uint = {}", k, *v); 
     } else { 
      println!("[\"{}\"]: ? = {}", k, v); 
     } 
    } 
} 

При запуске он выдает:

{c: Box<Any>, a: Box<Any>, b: Box<Any>} 
["c"]: ? = Box<Any> 
["a"]: &str = "blah" 
["b"]: uint = 42 
Смежные вопросы