【问题标题】:Aliasing trait inheritance with generics使用泛型对特征继承进行别名
【发布时间】:2016-06-11 10:58:49
【问题描述】:

我开始使用 Rust 开发一个新库。我试图围绕可能的方法来实现以下内容。

接下来更多的是想要的表达,而不是真正的语法。我试图表达这一点的所有方式要么不编译,要么在我去实现一个别名特征时不编译。

struct ConcreteType;
struct CommonType;

trait Handler<Rin, Rout = Rin>{
    fn handle_event(&self, msg: &Rin);
}

// alias Handler with one of the types defined as a common case
trait HandlerToMessage<M> : Handler <ConcreteType, M>{
    fn handle_event(&self, msg: &ConcreteType) {
        // default implementation of parent trait
        // example is simplified, forget about how Rout/M is actually used
        self.decode(msg)
    }

    // method to implement
    fn decode(&self, msg: &ConcreteType) -> M;
}

// another alias for most common case where Rin/Rout are ConcreteType, CommonType most often
trait HandlerToCommonType : HandlerToMessage <ConcreteType, CommonType>{
    fn decode(&self, msg: &ConcreteType) -> CommonType 
    {
       ...
    };
}

使用关联类型的替代方法

trait Handler{
    type Rin;
    type Rout;    // not yet able to do Rout = Rin with associated types

    fn handle_event(&self, msg: &Self::Rin) -> Self::Rout;
}


trait HandlerToMessage : Handler <Rin=ConcreteType>{
    fn handle_event(&self, msg: &Self::Rin) {
        // common functionality
        self.decode(msg)
    }

    // method to implement
    fn decode(&self, msg: &Self::Rin) -> Self::Rout;
}

trait HandlerToCommonType : HandlerToMessage <Rout=CommonType>{

    fn decode(&self, msg: &ConcreteType) -> CommonType
    {
        ...
    } 
}

在 C++ 中,这大致就是我想要完成的目标

// real world example I've seen in the wild of this structure
template <class Rout>
class Context {
public:
    void dispatch(Rout* msg);
};

template <class Rin, Rout = Rin>
class ReadHandler {
public:
    void read (Context* ctx, Rin* msg) = 0;

private:
    Context<Rout> ctx_;
};

// very common to convert from a byte buffer some message type
template <class M>
class BytesToMessageDecoder : ReadHandler<IOBuffer, M> {
public:
    // Template method pattern
    void read (Context* ctx, IOBuffer* msg) {
        M msgOut;
        bool success;
        success = this->decode(msg, &msgOut);
        if (success) {
            ctx->dispatch(msgOut);
        }                
    }

    bool decode(IOBuffer* msg, M* msgOut) = 0;

}

// convert one byte buffer to another is common
typedef BytesToMessageDecoder<IOBuffer> BytesToBytesDecoder;


// Concrete implementations
// look for fixed number of bytes incoming
class FixedLengthFrameDecoder : BytesToBytesDecoder {
    bool decode(IOBuffer* msg, IOBuffer* msgOut) { ... }
}

// fields are prefixed with a length. Wait for that many bytes and then dispatch
class LengthBasedFieldDecoder: BytesToBytesDecoder {
    bool decode(IOBuffer* msg, IOBuffer* msgOut) { ... }
}

class StringDecoder : BytesToMessageDecoder<std::string> { 
    // decode from byte buffer to a string
    bool decode(IOBuffer* msg, std::string* msgOut) { ... }
}

基本上顶级特征Handler 是最通用的,但可能不打算由高级库用户以外的任何人实现。 HandlerToMessage 特征是一种常见的转换,我们将ConcreteType 转换为其他类型。该库可以实现其中的几个。 HandlerToCommonType 是许多库类型想要从最常见的情况开始。

Rout 如何在 Handler 特征中使用的细节并不重要。我试图简化这个例子,并留下一些论据,希望能让我想要表达的内容更简洁。我对此的所有搜索要么让我认为这是不可能传达的,要么我在滥用它。我不太明白这是否属于新的专业化实现,但从我的理解来看并不像。

我意识到 Rust 不是 C++,所以也许我正在尝试做的事情要么不受支持,要么具有不同的语法。任何帮助都以正确的语法或更惯用的 Rust 方式表示赞赏。

【问题讨论】:

  • 你的第一个例子根本没有使用Rout
  • @Shepmaster 我编辑了 C++ 示例以使其更加真实,我希望因为我不肯定我可以在 Rust 中传达这个想法。如果我能以某种方式更清楚,请告诉我。谢谢你一直陪着我,非常感谢。

标签: rust


【解决方案1】:

也许您可以只拥有单独的特征并为另一个的所有实现者实现一个:

struct ConcreteType;
struct CommonType;

trait Handler<Input, Output = Input> {
    fn handle_event(&self, msg: &Input) -> Output;
}

trait HandlerToMessage<M> {
    fn decode(&self, msg: &ConcreteType) -> M;
}

impl<T, M> Handler<ConcreteType, M> for T
    where T: HandlerToMessage<M>
{
    fn handle_event(&self, msg: &ConcreteType) -> M {
        self.decode(msg)
    }
}

impl HandlerToMessage<CommonType> for () {
    fn decode(&self, _msg: &ConcreteType) -> CommonType {
        unimplemented!()
    }
}

fn main() {}

最后一个真的很尴尬,因为你通常会为具体类型实现一个特征,但你并没有真正提出任何有意义的实现。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多