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

c# – 有关转换和继承的乐趣

发布时间:2020-12-16 00:13:45 所属栏目:百科 来源:网络整理
导读:注意:这个问题是用C#编写的伪代码,但我真的要问哪些语言有解决方案.请不要挂断语法. 说我有两个班: class AngleLabel: CustomLabel { public bool Bold; // Just upping the visibility to public // code to allow the label to be on an angle } class L
注意:这个问题是用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).
 }

他们都脱离了这堂课:

class CustomLabel
 {
     protected bool Bold;
 }

粗体字段在下属类中公开为公共字段.

这些类上没有可用的接口.

现在,我有一个方法,我希望能够传递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;
     }
 }

可能会做一个演员然后在一个变量上设置粗体会很好.

我正在思考的是创建第四个类,它只暴露粗体变量并将我的自定义标签投射到该类.

那会有用吗?

如果是这样,它会使用哪种语言? (此示例来自旧版本的Delphi(Delphi 5)).我不知道它是否适用于那种语言,(我仍然需要尝试一下)但我很好奇它是否适用于C,C#或Java.

如果没有,任何关于什么会有用的想法? (记住没有提供接口,我也无法修改类.)

有谁猜?

解决方法

它适用于Delphi.与其使用的类相同的单元中的代码具有对受保护(但不是严格受保护)成员的隐式访问权限,甚至是在另一个单元中声明的成员.您在CustomLabel中声明受保护的属性:

type
  CustomLabel = class
  private
    FBold: Boolean;
  protected
    property Bold: Boolean read FBold write FBold;
  end;

另一个单元中的粗体设置过程将拥有自己的CustomLabel后代:

type
  TAccessCustomLabel = class(CustomLabel);

procedure SetBold(customLabel: CustomLabel)
begin
  TAccessCustomLabel(customLabel).Bold := True;
end;

您不能在其上使用as cast,因为实际参数永远不会是TAccessLabel的实例.它将是AngleLabel或NormalLabel的一个实例,但由于所有三个类从CustomLabel继承的部分都是通用的,因此Bold属性在所有这些部分中都是相同的.即使在财产被公布或在后代发布之后,这仍然是正确的:

type
  AngleLabel = class(CustomLabel)
  public
    property Bold;
  end;

您可以更改属性的可见性,但不能更改字段.如果你对一个字段尝试相同的事情,你将声明一个具有隐藏继承字段的同名的新字段.

您可以在C中执行类似的操作,但它并不像Delphi中那样常用,因此它可能会引起一些愤怒,特别是如果您打算编写可移植代码.

声明第四个类,就像在Delphi中一样.对于成员访问来说,C并不像Delphi那样松散,但它具有友谊的概念,在这种情况下也可以正常工作.

class AccessCustomLabel: public CustomLabel
{
  friend void SetLabel(CustomLabel* customLabel);
};

该函数现在可以完全访问该类的成员:

void SetLabel(CustomLabel* customLabel)
{
  // Not allowed:
  // customLabel->bold = true

  // Not ordinarily allowed; requires friendship
  reinterpret_cast<AccessCustomLabel*>(customLabel)->bold = true;
}

这是技术上未定义的行为,因为我们已经将对象类型转换为它实际上没有的类型.我们依赖于CustomLabel的所有后代具有相同的布局,特别是对于AccessCustomLabel的粗体成员,它与任何其他CustomLabel后代的粗体成员位于相同的相对位置.

Delphi和C代码中的类型转换执行类型惩罚.你不会在C#或Java中侥幸逃脱;他们检查他们的演员表的结果,所以如果customLabel没有真正持有AccessCustomLabel的实例,你将得到一个例外.您必须使用反射来访问这些语言中不相关类的受保护成员.证明这超出了我的深度.

(编辑:李大同)

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

    推荐文章
      热点阅读