在我的应用程序中,我需要为第三方控件添加一些额外的功能。
一个例子是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分类/包。
有没有办法添加实现这个?
答案 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"> </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的所有属性),但也许你可以避免一些双重编码。