< 返回版块

TsuITOAR 发表于 2021-05-17 18:36

Tags:trait,generics,associated constants

我需要一个从String中读取注释和数据的trait,其中注释有特定的标记,我使用了Pattern trait来实现。

trait foo<'a, P>
where
    P: Pattern<'a>
{
    const PATTERN: P;
} 

为类实现这个trait需要把P的实际类型声明两次

impl<'a> foo<'a, char> for bar{  
    const PATTERN: char = '%';  
}  

这样有点违背'DRY'原则。
并且,为这种具有泛型参数的trait去实现另一个trait时,就会发生the type parameter is not constrained错误,而在这里我的泛型参数只是为了关联常量定义的,一个类往往只会实现一次该trait,但因为这个泛型参数的原因会为阻碍实现其他trait。 使用关联类型来定义类型P可以减少一个泛型参数,但是生命周期泛型参数无法避免。

trait foo<'a>
{
    type P: Pattern<'a>;
    const PATTERN: Self::P;
} 

impl<'a> foo<'a> for bar{ 
    type P = char;
    const PATTERN: char = '%';  
}

并且仍然需要声明两次P。
有什么比较好的设计模式或者语法结构可以避免这些弊端吗?

评论区

写评论
作者 TsuITOAR 2021-05-18 13:06

谢谢你的回复,事实上我的疑问是: 1.如何取消关联类型的泛型参数,因为我的这个trait事实上不是一个泛型trait,这一点我已经解决了 2.如何避免重复两次指明P的实际类型

--
👇
Neutron3529: 总觉得你需要的是 const PATTERN: Self::P="what ever you want";

就像这样:

#![feature(pattern)]
use std::str::pattern::Pattern;
trait foo<'a>
{
    type P: Pattern<'a>;
    const PATTERN: Self::P;
} 
struct bar();
impl<'a> foo<'a> for bar{ 
    type P = char;
    const PATTERN:Self::P = '%';  
}
struct baz();
impl<'a> foo<'a> for baz{
    type P = &'a str;
    const PATTERN: Self::P="asd";
}
fn main(){
    println!("{}",bar::PATTERN);
    println!("{}",baz::PATTERN)
}

<'a,P>的用法是,允许同一个结构体的type P不同

<'a>的用法是,每个同类结构体的PATTERN必须具有相同的type(但不同类(比如这里的bar跟baz)可以不同)

作者 TsuITOAR 2021-05-18 13:05

重新看了一下Pattern trait的文档,应该这样定义和实现我的trait

trait foo
{
    type P: for<'a> Pattern<'a>;
    const PATTERN: Self::P;
} 

impl foo for bar{ 
    type P = char;
    const PATTERN: char = '%';  
}

这样就没有泛型参数了,但是仍然需要显示指定PATTERN类型,尽管在trait定义中已经完全限制了,如果有更合适的写法还请大家分享

Neutron3529 2021-05-17 21:08

总觉得你需要的是 const PATTERN: Self::P="what ever you want";

就像这样:

#![feature(pattern)]
use std::str::pattern::Pattern;
trait foo<'a>
{
    type P: Pattern<'a>;
    const PATTERN: Self::P;
} 
struct bar();
impl<'a> foo<'a> for bar{ 
    type P = char;
    const PATTERN:Self::P = '%';  
}
struct baz();
impl<'a> foo<'a> for baz{
    type P = &'a str;
    const PATTERN: Self::P="asd";
}
fn main(){
    println!("{}",bar::PATTERN);
    println!("{}",baz::PATTERN)
}

<'a,P>的用法是,允许同一个结构体的type P不同

<'a>的用法是,每个同类结构体的PATTERN必须具有相同的type(但不同类(比如这里的bar跟baz)可以不同)

1 共 3 条评论, 1 页