我的印象是这两件事只是在语义上不同。
然而,这是可能的:
struct Foo;
trait Bar<T> {
fn resolve(&self) -> T;
}
impl Bar<isize> for Foo {
fn resolve(&self) -> isize {
return 0isize;
}
}
impl Bar<usize> for Foo {
fn resolve(&self) -> usize {
return 1usize;
}
}
#[test]
fn test_foo() {
let foo = Foo;
assert!((&foo as &Bar<isize>).resolve() == 0isize);
assert!((&foo as &Bar<usize>).resolve() == 1usize);
}
虽然不是这样:
struct Foo;
trait Bar {
type T;
fn resolve(&self) -> Self::T;
}
impl Bar for Foo {
type T = isize;
fn resolve(&self) -> isize {
return 0isize;
}
}
impl Bar for Foo {
type T = usize;
fn resolve(&self) -> usize {
return 1usize;
}
}
#[test]
fn test_foo() {
let foo = Foo;
assert!((&foo as &Bar<T = isize>).resolve() == 0isize);
assert!((&foo as &Bar<T = usize>).resolve() == 1isize);
}
它生成:
<anon>:8:1: 13:2 error: conflicting implementations for trait `Bar` [E0119]
<anon>: 8 impl Bar for Foo {
<anon>: 9 type T = isize;
<anon>:10 fn resolve(&self) -> isize {
<anon>:11 return 0isize;
<anon>:12 }
<anon>:13 }
我错过了什么吗?
我正在尝试实现的是什么特殊语法,还是在通用和相关类型之间存在真正的......技术......区别?
在某些情况下,相关类型与使用通用类型相比具有有形(而不是纯粹的代码漂亮)优势吗?
答案 0 :(得分:5)
我将重复我的评论:类型参数和相关类型在语义上是不同的。然而,这是为什么它们都存在于语言中的要点 - 它们各自独立的工作,所以它不是“只是”语义差异,它是它们作为一个单独存在的全部原因来自类型参数的东西。
请注意,我甚至没有触及语法差异。当然,存在语法差异是绝对自然的。毕竟这些是独立的功能;如果他们有没有语法上的差异,那么你如何区分它们呢?它们的语法差异与语义差异紧密相关,因为定义相关类型的方式清楚地表明它们具有“输出”位置,与类型参数的“输入”位置相比,但在技术上它们都是类型参数和相关类型(以及顺便提一句,隐含的Self
参数也是一样的。
答案 1 :(得分:0)
对于发现此问题的任何其他人,类型参数和相关类型之间也存在另一个技术区别。
如果您尝试使用关联类型实现特征,则可能会看到错误:
src/lib.rs:10:1: 15:2 error: the impl does not reference any types
defined in this crate; only traits defined in the current crate can
be implemented for arbitrary types [E0117]
如果您在箱子栏中导出了特征:
pub trait BarParam<TRtn> {
fn bar() -> TRtn;
}
pub trait BarAssoc {
type TRtn;
fn bar() -> Self::TRtn;
}
你会发现导入这些特征的箱子只能实现:
impl<'a> BarParam<Foo> for &'a str {
fn bar() -> Foo {
return Foo;
}
}
尝试实施时:
impl<'a> BarAssoc for &'a str {
type TRtn = Foo;
fn bar() -> Foo {
return Foo;
}
}
会导致上述错误。
坦率地说,我不确定这里发生了什么,所以如果你这样做,请务必添加评论或其他答案;但这是在你写箱子时避免相关类型的实际原因。