将字段和方法添加到从相同基类继承而不修改基类的类

时间:2016-06-22 11:27:36

标签: delphi pascal lazarus

在我的应用程序中,我需要为第三方控件添加一些额外的功能。

一个例子是TcxLabel和TcxDBLabel(来自DevExpress)。 两者都从相同的基类继承。

对于那些控件,我想添加一些字段和方法。

我今天这样做的方式:

TMycxLabel = class(TcxLabel)
private
  FMyField1: string;
  FMyField2: Integer;
public 
  procedure DoSomething;
end;

TMycxDBLabel = class(TcxDBLabel)
private
  FMyField1: string;
  FMyField2: Integer;
public 
  procedure DoSomething;
end;

所以基本上我必须写两次。

实现它的一种方法是修改这两个控件继承的基类。 但这不是一个选项 - 不应修改DevExpress分类/包。

有没有办法添加实现这个?

3 个答案:

答案 0 :(得分:2)

  

有没有办法添加实现这个?

不,没有。任何可行的解决方案都基本上等同于您当前的方法。由于您需要与实例关联的状态,因此您实际上需要将其作为实例的一部分。这将引导您找到解决方案。

您可以考虑劫持像Tag这样的字段来存储该状态,但这是错误的,因为Tag保留供该类型的消费者使用。其他合理的解决方案可能涉及维护一个单独的列表,该列表将实例映射到此附加状态。你可以做到这一点,但在我看来,它会比另类更糟糕。

最有效的方法是将字段添加到公共基类中,但由于涉及修改第三方代码,因此您已将其排除在外。

答案 1 :(得分:1)

有一种方法,虽然它只会在您只需要基类中可用的内容时才会起作用。 例如,如果TcxDBLabel继承自TcxLabel,只要您只使用TcxDBLabel的TcxLabel部分(字段,方法和属性),就可以向两者添加一个方法(松散地说)。

我指的是类型转换

我应该警告说,使用这种做法并不是双方同意的。许多开发人员认为类型转换是一种不好的做法,而我自己倾向于仅将其作为最后的手段使用。但是,我会告诉你关于天气的哲学讨论,你应该或不应该使用它。

所以如果你创建一个这样的子类:

THcxLabel = Class(TcxLabel)
private
  FMyField1: string;
  FMyField2: Integer;
public
  procedure DoSomething;
End;

然后,您可以将其添加到任何基于TcxLabel的类实例,如下所示:

THcxLabel(cxLabel1).DoSomething;
THcxLabel(cxDBLabel1).DoSomething;

就像我说的那样,在DoSomething方法中没有来自TcxDBLabel的细节,但您将能够使用基类资源。

答案 2 :(得分:0)

你可以继承一次虚拟类(这是你的"),在那里定义新的字段,然后从那里继承两个新的类吗?

根据评论进行修改:

你可以试试像这样的人。

在您继承的类中,只需添加一个公共数据成员,它本身就是一个类,您可以在其中定义自己的东西......看起来像:

 $("<div>This is  content</div>")
                                        .dialog({
                                            "title": "",
                                            "width": "auto",
                                            "height": "auto",
                                            "modal": true,

                                            //                "buttons": {"OK": function() {
                                            //                $(this).dialog("close");
                                            //                },
                                            //                "Refresh": function() {
                                            //                getContent($(preview_btn).attr('data-id'));
                                            //                },
                                            //                }
                                        }).dialogExtend({
"load": function (evt, dlg) {
                                                getContent($(preview_btn).attr('data-id'), c_page);
                                                //$('.ui-dialog').css('top', '95px');
                                                //$("html, body").animate({
                                                // scrollTop:0
                                                //},"fast");

                                                $('span').removeClass('ui-button-icon-primary ui-icon');
                                                //$('span').remove();
                                                $('.ui-button').css('top', '5px');
                                                //$('.ui-dialog-titlebar-close').append('<span class="test">&nbsp;&nbsp;&nbsp;&nbsp;</span>');
                                                //$('.ui-dialog-titlebar-close').append('<span class="ui-button-text">Close</span>');
                                                $('.ui-dialog-titlebar-close').append('<div style="margin-top: -12px;">X</div>');
                                                $('.ui-dialog').css('top', scrollY + 'px');
                                                $('.ui-button-text').css({"margin-top": "1px", "height": "0px"});

                                            },
       });



    function getContent(id, c_page) {
                                // console.log(id);
                                $.ajax({
                                    type: 'post',
                                    url: 'xxx.php',
                                    //url: 'preview_template.php',
                                    data: {id: id, c_page: c_page},
                                    success: function (data) {
                                        $('body').find('.ui-dialog-content').html(data);
                                        var full_size = $(window).width();
                                        var ui_size = $('.ui-dialog').width();
                                        // console.log(full_size);
                                        // console.log(ui_size);
                                        var ui_left = (parseFloat(full_size) - parseFloat(ui_size)) / 2;
                                        $('.ui-dialog').css('left', ui_left + 'px');
                                    }
                                })
                            }

然后将其称为

TMycxLabel = class(TcxLabel)
public
  MyStuff: TMyStuff;
end;

TMyStuff = class()
private
  FMyField1: string;
  FMyField2: Integer;
public 
  procedure DoSomething;
end;

我意识到这并没有完全回答你的问题,并且不能用于几个用例(你不能以这种方式从MyStuff访问TMycxLabel的所有属性),但也许你可以避免一些双重编码。