Vac*_*ano 3 c# c++ delphi inheritance casting
注意:这个问题是用C#编写的伪代码,但我真的要问哪些语言有解决方案.请不要挂断语法.
说我有两个班:
class AngleLabel: CustomLabel
{
public bool Bold; // Just upping the visibility to public
// code to allow the label to be on an angle
}
class Label: CustomLabel
{
public bool Bold; // Just upping the visibility to public
// Code for a normal label
// Maybe has code not in an AngleLabel (align for example).
}
Run Code Online (Sandbox Code Playgroud)
他们都脱离了这堂课:
class CustomLabel
{
protected bool Bold;
}
Run Code Online (Sandbox Code Playgroud)
粗体字段在下属类中公开为公共字段.
这些类上没有可用的接口.
现在,我有一个方法,我希望能够传递CustomLabel并设置Bold属性.可以这样做而不必1)找出对象的真实类是什么,2)强制转换为该对象,然后3)为每个标签类型的每个变量制作单独的代码以设置粗体.有点像这样:
public void SetBold(customLabel: CustomLabel)
{
AngleLabel angleLabel;
NormalLabel normalLabel;
if (angleLabel is AngleLabel )
{
angleLabel= customLabel as AngleLabel
angleLabel.Bold = true;
}
if (label is Label)
{
normalLabel = customLabel as Label
normalLabel .Bold = true;
}
}
Run Code Online (Sandbox Code Playgroud)
可能会做一个演员然后在一个变量上设置粗体会很好.
我正在思考的是创建第四个类,它只暴露粗体变量并将我的自定义标签投射到该类.
那会有用吗?
如果是这样,它会使用哪种语言?(此示例来自旧版本的Delphi(Delphi 5)).我不知道它是否适用于那种语言,(我仍然需要尝试一下)但我很好奇它是否适用于C++,C#或Java.
如果没有,任何关于什么会有用的想法?(记住没有提供接口,我也无法修改类.)
有谁猜?
它适用于Delphi.与其使用的类相同的单元中的代码具有对受保护(但不是严格受保护)成员的隐式访问权限,甚至是在另一个单元中声明的成员.您将声明受保护的财产CustomLabel:
type
CustomLabel = class
private
FBold: Boolean;
protected
property Bold: Boolean read FBold write FBold;
end;
Run Code Online (Sandbox Code Playgroud)
另一个单元中的大胆设置程序将有自己的CustomLabel后代:
type
TAccessCustomLabel = class(CustomLabel);
procedure SetBold(customLabel: CustomLabel)
begin
TAccessCustomLabel(customLabel).Bold := True;
end;
Run Code Online (Sandbox Code Playgroud)
你不能使用as强制转换因为实际参数永远不会是实例TAccessLabel.它将是AngleLabel或的实例NormalLabel,但由于CustomLabel所有三个类继承的部分都是通用的,因此Bold所有这些属性都相同.即使在财产被公布或在后代发布之后,这仍然是正确的:
type
AngleLabel = class(CustomLabel)
public
property Bold;
end;
Run Code Online (Sandbox Code Playgroud)
您可以更改属性的可见性,但不能更改字段.如果您对字段尝试相同的操作,您将声明一个具有相同名称的新字段,以隐藏继承的字段.
您可以在C++中执行类似的操作,但它并不像在Delphi中那样常用,因此它可能会引起一些愤怒,特别是如果您打算编写可移植代码.
声明第四个类,就像在Delphi中一样.C++并不像Delphi那样松散于成员访问,但它具有友谊的概念,在这种情况下也是如此.
class AccessCustomLabel: public CustomLabel
{
friend void SetLabel(CustomLabel* customLabel);
};
Run Code Online (Sandbox Code Playgroud)
该函数现在可以完全访问该类的成员:
void SetLabel(CustomLabel* customLabel)
{
// Not allowed:
// customLabel->bold = true
// Not ordinarily allowed; requires friendship
reinterpret_cast<AccessCustomLabel*>(customLabel)->bold = true;
}
Run Code Online (Sandbox Code Playgroud)
这是技术上未定义的行为,因为我们已经将对象类型转换为它实际上没有的类型.我们依赖于所有后代CustomLabel具有相同的布局,特别是对于一个bold成员AccessCustomLabel来说,它bold与任何其他CustomLabel后代的成员位于相同的相对位置.
Delphi和C++代码中的类型转换执行类型惩罚.你不会在C#或Java中侥幸逃脱; 他们检查他们的演员表的结果,所以如果customLabel没有真正持有一个实例AccessCustomLabel,你会得到一个例外.您必须使用反射来访问这些语言中不相关类的受保护成员.证明这超出了我的深度.