通过继承与对象引用进行回调

Callback via inheritance vs object reference

本文关键字:回调 对象引用 继承      更新时间:2023-10-16

比较以下两个变体(应该做同样的事情(

class Foo
    {
    public:
        void void doStuff()
            {
            //...
            doStuffImpl();
            //...
            }
        virtual void doStuffImpl()=0;
        void affectStateInFoo()
            {}
    };
class Bar:public Foo
    {
    public:
        void doStuffImpl()
            {
            affectStateInFoo();
            }
    };

class Foo;
class Callback
    {
    public:
        virtual void doStuff(Foo& foo)=0;
    };
class Foo
    {
    public:
        Foo(Callback& o):obj(o){}
        void void doStuff()
            {
            //...
            obj.doStuff(*this);
            //...
            }
        void affectStateInFoo()
            {}
        Callback& obj;
    };
class Bar:public Callback
    {
    public:
        void doStuff(Foo& foo)
            {
            foo.affectStateInFoo();
            }
    };

什么时候首选两种变体之一?

你的第一种方法需要Bar继承自Foo,这与这些类紧密结合。对于回调,这并不总是您想要做的。您的第二种方法不需要这样做。

如果您实际扩展类,我会使用第一种方法,但对于通知,我会使用第二种方法,或者如 Igor R. 在注释中提到的函数指针,如对象。

我更喜欢第二个,因为它更容易通过模拟进行单元测试。但这只是我的意见。

每次继承过度是面向对象新手的常见失败。

使用委派(您称之为回调(通常更灵活。

  • 类数较少
  • "回调"类的可能重用
  • 可在运行时而不是编译时交换