कुछ घटना स्रोत की कल्पना करो, जो एक enum के रूप में प्रतिनिधित्व घटनाओं का उत्पादन करता है। बेशक, सबसे अच्छा दक्षता के लिए, इस निर्माता शून्य-प्रतिलिपि, है यानी वह अपने आंतरिक बफ़र्स के लिए संदर्भ देता है:उधार प्रकार को उधार प्रकार को संदर्भ के लिए क्यों आवश्यकता होती है?
enum Variant<'a> {
Nothing,
SomeInt(u64),
SomeBytes(&'a [u8])
}
impl Producer {
fn next(&'a mut self) -> Variant<'a> { ... }
}
यह उपभोक्ताओं कि अग्रदर्शी या बैक ट्रैकिंग की आवश्यकता नहीं है के लिए पूरी तरह से ठीक है, लेकिन कभी कभी एक घटनाओं के कुछ अनुक्रम को बचाने की जरूरत है। इस प्रकार, हमारे Variant
प्रकार एक सामान्य हो जाता है:
enum Variant<BytesT> {
Nothing,
SomeInt(u64),
SomeBytes(BytesT)
}
type OwnedVariant = Variant<Vec<u8>>;
type BorrowedVariant<'a> = Variant<&'a [u8]>;
यहाँ, हम "मालिक-संदर्भ" संबंध है, जो जोड़े Vec<T>
के समान है के साथ दो प्रकार के साथ अंत - &[T]
, String
- &str
। डॉक्स builtin लक्षण Borrow
और ToOwned
जो सिर्फ क्या एक सूक्ष्म अति सूक्ष्म अंतर के अलावा आवश्यक है प्रदान करते हैं सुझाव देते हैं:
trait Borrow<Borrowed: ?Sized> {
fn borrow(&self) -> &Borrowed;
// this: -----------^
}
pub trait ToOwned {
type Owned: Borrow<Self>;
fn to_owned(&self) -> Self::Owned;
}
borrow
का परिणाम कुछ, जो स्पष्ट रूप से BorrowedVariant<'a>
नहीं है करने के लिए एक संदर्भ होना आवश्यक है। इस आवश्यकता को निकाला जा रहा है इस समस्या का हल (यहाँ, नाम alt लगी होती हैं इस तथ्य पर जोर देना इस एक वैकल्पिक इंटरफ़ेस है):
trait AltBorrow<'a, AltBorrowed> {
fn alt_borrow(&'a self) -> AltBorrowed;
}
trait AltToOwned<'a> {
type AltOwned: AltBorrow<'a, Self>;
fn alt_to_owned(&'a self) -> Self::AltOwned;
}
यह विशेषता तो मानक प्रकार के लिए लागू किया जा सकता है, उदा Vec
:
impl<'a, T> AltBorrow<'a, &'a [T]> for Vec<T> {
fn alt_borrow(&'a self) -> &'a [T] {
self.as_slice()
}
}
impl<'a, T> AltToOwned<'a> for &'a [T]
where T: Clone
{
type AltOwned = Vec<T>;
fn alt_to_owned(&'a self) -> Vec<T> {
self.to_vec()
}
}
साथ ही सवाल में Variant
enum के लिए:
impl<'a> AltBorrow<'a, BorrowedVariant<'a>> for OwnedVariant {
fn alt_borrow(&'a self) -> BorrowedVariant<'a> {
match self {
&Variant::Nothing => Variant::Nothing,
&Variant::SomeInt(value) => Variant::SomeInt(value),
&Variant::SomeBytes(ref value) => Variant::SomeBytes(value.alt_borrow()),
}
}
}
impl<'a> AltToOwned<'a> for BorrowedVariant<'a> {
type AltOwned = OwnedVariant;
fn alt_to_owned(&'a self) -> OwnedVariant {
match self {
&Variant::Nothing => Variant::Nothing,
&Variant::SomeInt(value) => Variant::SomeInt(value),
&Variant::SomeBytes(value) => Variant::SomeBytes(value.alt_to_owned()),
}
}
}
अंत में, सवाल:
- मैं मूल
Borrow
/ToOwned
अवधारणा का दुरुपयोग है? क्या मुझे इसे हासिल करने के लिए कुछ और उपयोग करना चाहिए? - यदि नहीं, तो
std::borrow
से वर्तमान कम-सामान्य इंटरफ़ेस को क्यों पसंद किया जा सकता है?