Я рекомендую прочитать этот вопрос , в котором содержится много полезной информации о том, почему вы не можете использовать дженерики с методами черты, если хотите использовать их в качестве объектов.
Короткий ответ: вы не можете делать то, что пытаетесь сделать: иметь функцию, которая принимает итератор любого типа (которая является связанной универсальной функцией), и при этом эта черта является объектобезопасной. [ 1118]
Есть несколько трюков, которые вы можете использовать , однако, это позволит вам манипулировать итераторами строк с помощью объекта-черты. Я рассмотрю каждый метод.
В Rust есть только два типа строк: String
и &str
. Как вы указали в своем ответе, вы хотите работать с обоими. В этом случае все, что вам нужно сделать, это сделать два разных метода:
pub trait Store {
fn query_valid_paths_str(&mut self, paths: &mut dyn Iterator- ) -> Vec
;
fn query_valid_paths_string(&mut self, paths: &mut dyn Iterator- ) -> Vec
;
}
Теперь, это становится нелогичным в определенный момент, если у вас слишком много типов, с которыми вы имеете дело. Но если есть только два, это самый простой вариант.
Если вы хотите использовать вместо этого IntoIterator
, сигнатуры функций будут выглядеть следующим образом:
pub trait Store {
fn query_valid_paths_str(&mut self, paths: &mut dyn IntoIterator, Item = &str>) -> Vec;
fn query_valid_paths_string(&mut self, paths: &mut dyn IntoIterator, Item = String>) -> Vec;
}
Box
и динамическую диспетчеризацию Этот подход гораздо более сложный и, вероятно, не стоит усилий, но я приведу его здесь в качестве доказательства концепции.
pub trait Store {
fn query_valid_paths(&mut self, paths: &mut dyn Iterator- >) -> Vec
;
}
Здесь paths
- итератор над блоком, которому принадлежит объект черты AsRef
.
Это (насколько я знаю) единственный способ создать действительно полиморфное решение. Но какой ценой? Чтобы это работало, вам нужно не только явно объявить список, который вы передали как Vec
, это добавляет много накладных расходов при динамической диспетчеризации из указателей блока. Просто чтобы показать, насколько громоздким это может быть:
let mut str_vec: Vec>> = vec!(Box::new("string one"), Box::new("string two".to_string()));
some_store_object.query_valid_paths(&mut str_vec.iter());
Я не рекомендую этот метод, если вам абсолютно не нужны эти функции. Вместо этого используйте первый метод.
Если вы используете этот метод, но хотите использовать его с IntoIterator
, он будет выглядеть так:
pub trait Store {
fn query_valid_paths(&mut self, paths: &mut dyn IntoIterator>>, Item = Box>>) -> Vec;
}
Я думаю, что Вы имеете изящное решение, но это работает.
XAML:
<ListView Name="listviewNames">
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn
Header="Number"
DisplayMemberBinding="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type ListViewItem}},
Converter={StaticResource IndexConverter}}" />
<GridViewColumn
Header="Name"
DisplayMemberBinding="{Binding Path=Name}" />
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
ValueConverter:
public class IndexConverter : IValueConverter
{
public object Convert(object value, Type TargetType, object parameter, CultureInfo culture)
{
ListViewItem item = (ListViewItem) value;
ListView listView = ItemsControl.ItemsControlFromItemContainer(item) as ListView;
int index = listView.ItemContainerGenerator.IndexFromContainer(item);
return index.ToString();
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}