2017-01-23 17 views
5

Tôi muốn có một chức năng foo lấy một thể hiện của một loại thực hiện một đặc điểm A. Tôi luôn luôn thích sử dụng Generics để có công văn tĩnh:Thực hiện chức năng cho người triển khai đặc điểm với công văn động và tĩnh

trait A {} 

fn foo<T: A>(t: T) {} 

Tuy nhiên, phương pháp này giới thiệu một số cứng nhắc, tôi không thể vượt qua một đối tượng đặc điểm giống như ở đây:

trait A {} 

fn foo(t: &A) {} 

Các là, đôi khi tôi biết loại và đôi khi không. Có cách nào để có cả hai công văn động cho các đối tượng trait và công văn tĩnh để biên dịch các loại được biết đến trong khi không thực hiện những thứ hai lần?

Trả lời

6

Điều đó thực sự có thể xảy ra. Một lựa chọn là để thực hiện một cách rõ ràng A với nhiều loại tài liệu tham khảo của nó:

impl<'a, T: A + ?Sized> A for &'a T {} 

Đối số sẽ trở thành một đối tượng đặc điểm khi T = &A, trong khi vẫn làm công văn tĩnh cho implementors tiếng của A. Các mã sau đây bây giờ sẽ biên dịch:

fn foo<T: A>(a: T) {} 

struct MyA; 
impl A for MyA {} 

fn main() { 
    foo(MyA{}); 
    foo(&MyA{}); 
    foo(&MyA{} as &A); 
} 

Nếu bạn sẵn sàng để luôn luôn vượt qua một đối số mượn, bạn cũng có thể làm điều này thay vì:

fn foo<T: A + ?Sized>(a: &T) {} 

Đối số sẽ trở thành một đối tượng đặc điểm khi T = A.

+0

Tôi không chắc chắn nếu tôi hoàn toàn hiểu 'fn foo' của bạn. Không phải luôn luôn có một ràng buộc tiềm ẩn trên 'Sized'? – torkleyy

+1

@torkleyy Trên đối số chức năng, vâng. Đó là ok bởi vì những gì chúng tôi đang cung cấp thực sự luôn luôn có kích thước, trong cả hai trường hợp. Hàm thứ hai nhận '& T', có kích thước, ngay cả khi T không phải. –

Các vấn đề liên quan