2016-09-14 15 views
7

Có thể định nghĩa các hàm bên trong các đặc điểm khi có các kiểu trả về impl Trait không? Tôi muốn tạo ra một đặc điểm có thể được thực hiện bởi nhiều cấu trúc để các hàm new() của tất cả chúng trả về một đối tượng mà tất cả chúng có thể được sử dụng theo cùng một cách mà không cần phải viết mã cụ thể cho từng đối tượng.Sử dụng impl Trait trong định nghĩa Trait

#![feature(conservative_impl_trait)] 

trait A { 
    fn new() -> impl A; 
} 

Tuy nhiên, tôi nhận được lỗi sau:

impl Trait not allowed outside of function and inherent method return types

Đây có phải là chỉ là một hạn chế của việc thực hiện hiện tại của impl Trait ở Rust hay tôi đang sử dụng nó sai?

Trả lời

5

Nếu bạn chỉ cần trả lại loại cụ thể mà đặc điểm hiện đang được triển khai, bạn có thể đang tìm kiếm Self.

trait A { 
    fn new() -> Self; 
} 

Ví dụ, điều này sẽ biên dịch:

trait A { 
    fn new() -> Self; 
} 

struct Person; 

impl A for Person { 
    fn new() -> Person { 
     Person 
    } 
} 

Hoặc một ví dụ đầy đủ hơn, thể hiện bằng cách sử dụng đặc điểm:

trait A { 
    fn new<S: Into<String>>(name: S) -> Self; 
    fn get_name(&self) -> String; 
} 

struct Person { 
    name: String 
} 

impl A for Person { 
    fn new<S: Into<String>>(name: S) -> Person { 
     Person { name: name.into() } 
    } 

    fn get_name(&self) -> String { 
     self.name.clone() 
    } 
} 

struct Pet { 
    name: String 
} 

impl A for Pet { 
    fn new<S: Into<String>>(name: S) -> Pet { 
     Pet { name: name.into() } 
    } 

    fn get_name(&self) -> String { 
     self.name.clone() 
    } 
} 

fn main() { 

    let person = Person::new("Simon"); 
    let pet = Pet::new("Buddy"); 

    println!("{}'s pets name is {}", get_name(&person), get_name(&pet)); 
} 

fn get_name<T: A>(a: &T) -> String { 
    a.get_name() 
} 

Playground

Như một mặt lưu ý .. Tôi đã sử dụng String ở đây có lợi cho tài liệu tham khảo &str .. để giảm e sự cần thiết cho cuộc sống rõ ràng và có khả năng mất tập trung vào câu hỏi trong tầm tay. Tôi tin rằng nó thường là quy ước để trở về một tài liệu tham khảo &str khi vay nội dung và có vẻ thích hợp ở đây .. tuy nhiên tôi không muốn đánh lạc hướng từ ví dụ thực tế quá nhiều.

+0

Huh; không có ý tưởng đó là có thể! Cảm ơn nhiều. – Ameo

+1

Bạn đang rất hoan nghênh! :) –

+2

Điều này không giống như trả về 'impl Trait'. Ví dụ, bạn không thể thêm một phương thức mà trong 'Person' trả về một' Pet' nhưng trong 'Pet' trả về một' Person', mặc dù cả hai đều thực thi 'A'. [RFC (1522)] (https://github.com/rust-lang/rfcs/blob/master/text/1522-conservative-impl-trait.md) đề cập đến giới hạn này và thể hiện mong muốn cuối cùng loại bỏ nó (viên đạn đầu tiên trong "Giới hạn ban đầu"). – trentcl

6

trentcl mentions, bạn hiện không thể đặt impl Trait ở vị trí trả lại của một phương pháp đặc điểm.

Từ RFC 1522:

impl Trait may only be written within the return type of a freestanding or inherent-impl function, not in trait definitions or any non-return type position. They may also not appear in the return type of closure traits or function pointers, unless these are themselves part of a legal return type.

  • Eventually, we will want to allow the feature to be used within traits [...]
+1

Cảm ơn một lần nữa Shepmaster. Tôi đã không xem xét điều này hoàn toàn vì vậy tôi thấy rằng câu trả lời của tôi không trực tiếp giải quyết các câu hỏi. Điều đó nói rằng, nó được chấp nhận bây giờ và dường như đã giúp OP. Làm cách nào để tiếp tục từ đây? Câu hỏi có lẽ nên được chỉnh sửa để loại bỏ việc sử dụng cụ thể của 'impl Trait' hay chúng ta nên làm việc để loại bỏ hoàn toàn câu trả lời? –

+2

@SimonWhitehead Tôi không muốn chỉnh sửa câu hỏi một cách quyết liệt. Tôi nghĩ sẽ ổn cả hai câu trả lời. Bạn có thể thay đổi câu trả lời của mình để nói điều gì đó như "mặc dù bạn chưa thể thực hiện * X *, đây là giải pháp có thể giúp". Trả lời câu hỏi trực tiếp và cung cấp các lựa chọn thay thế hữu ích đều là những đóng góp có giá trị. Dấu chọn chủ yếu có nghĩa là "câu trả lời này đã giúp OP nhiều nhất". Bình chọn có nghĩa là "câu trả lời này đã giúp tôi". – Shepmaster

+0

Không sao cả. Cảm ơn một lần nữa vì sự giúp đỡ! –

1

Bạn có thể nhận được một cái gì đó tương tự, ngay cả trong trường hợp nó không trở về "Tự", bằng cách đặt tên một cách rõ ràng kiểu trả về.

trait B {} 
struct C; 

impl B for C {} 

trait A { 
    type FReturn: B; 
    fn f() -> Self::FReturn; 
} 

struct Person; 

impl A for Person { 
    type FReturn = C; 
    fn f() -> C { 
     C 
    } 
} 
Các vấn đề liên quan