加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – 在不更改接口的情况下向对象添加功能

发布时间:2020-12-16 03:32:50 所属栏目:百科 来源:网络整理
导读:我有一个对象作为接口的引用/指针.如果存在该方法,我想在具体对象上调用一个方法,而不需要更改接口,破坏封装或编写任何可怕的黑客攻击.怎么做到呢? 这是一个例子. 我有一个界面: class IChatty{public: virtual ~IChatty() {}; virtual std::string Speak(
我有一个对象作为接口的引用/指针.如果存在该方法,我想在具体对象上调用一个方法,而不需要更改接口,破坏封装或编写任何可怕的黑客攻击.怎么做到呢?

这是一个例子.

我有一个界面:

class IChatty
{
public:
    virtual ~IChatty() {};
    virtual std::string Speak() const = 0;
};

并且这个界面的多个具体实现:

class SimpleChatty : public IChatty
{
public:
    ~SimpleChatty() {};

    virtual std::string Speak() const override
    {
        return "hello";
    }
};

class SuperChatty : public IChatty
{
public:
    void AddToDictionary(const std::string& word)
    {
        words_.insert(word);
    }
    virtual std::string Speak() const override
    {
        std::string ret;
        for(auto w = words_.begin(); w != words_.end(); ++w )
        {
            ret += *w;
            ret += " ";
        }
        return ret;
    }
private:
    std::set<std::string> words_;
};

SuperChatty :: AddToDictionary方法不存在于抽象的IChatty接口中,尽管它可以包含在另一个新接口中.

在现实世界中,这些对象是通过工厂构建的,它们本身是抽象接口的具体实例.然而,就我们的目的而言,这与手头的问题是正交的:

int main()
{
    IChatty* chatty = new SuperChatty;
    chatty->AddToDictionary("foo");
    std::cout << chatty->Speak() << std::endl;
}

由于AddToDictionary不是IChatty接口的一部分(并且不能成为其中的一部分),我可以称之为.

如何在不破坏封装,写一些可怕的黑客或采取任何其他设计快捷方式的情况下在chatty指针上调用AddToDictionary?

注意:在现实世界中,字典是SuperChatty对象本身的一部分,不能与它分开.

注2:我不想向下倾斜到具体类型.

解决方法

将字典作为SuperChatty可以更新和引用的对象:
class Dictionary {
public:
    void add(const std::string& word);
    const std::set<std::string>>& words() const;
    //..
};

class SuperChatty : public IChatty
{
public:
    SuperChatty(Dictionary& dictionary) :
    dictionary(dictionary) {
    }

    virtual std::string Speak() const override
    {
        auto words = dictionary.words();
        ostringstream oss;
        copy(words.begin(),words.end(),ostream_iterator<string>(oss," "));
        return oss.str();
    }
};

用法:

int main()
{   
    Dictionary dictionary;
    IChatty* chatty = new SuperChatty(dictionary);
    dictionary.add("foo");
    std::cout << chatty->Speak() << std::endl;
}

编辑

好的,问题改变了.

如果你正确地做到这一点,你需要将自己与糟糕的底层系统隔离开来:

struct Dictionary {
    virtual ~Dictionary () {}
    virtual void add(const std::string& word) = 0;
};

struct Instrumenter {
    virtual ~Instrumenter () {}
    virtual void addDictionary(Dictionary& dictionary) = 0;
};

struct Chatter {
    virtual ~Chatter() {}
    virtual string speak() const = 0;
    virtual void instrument(Instrumenter& instrumenter) = 0;
};

这些实现如下:

class BasicChatter : public Chatter {
    virtual string speak() const {
        return chatty.Speak();
    }
    virtual void instrument(Instrumenter& instrumenter) {
        // do nothing
    }
private:
    SimpleChatty chatty;
};

class SuperChatter : public Chatter {
    SuperChatter () : dictionary(chatty);

    virtual void instrument(Instrumenter& instrumenter) {
        instrumenter.addDictionary(dictionary);
    }

    virtual string speak() const {
        return chatty.Speak();
    }
private:
    SuperChatty chatty;
    DictionaryImpl dictionary;
};

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读