这个B实例是A实例的属性吗?

时间:2013-07-18 02:41:16

标签: c# oop

看看这个场景:

//base class
abstract class AAA { } 

//class 1
class BBB : AAA
{
     //Field of ZZZ type
     public ZZZ ZField = new ZZZ();
}

//class 2
class ZZZ
{
      public string foo() { return ImAPropertyOfAnAAADerivedClass ? "yes" : "no"; }

      bool ImAPropertyOfAnAAADerivedClass 
      {
          get { /* here */ }
      }
}

//running test
new BBB().ZField.foo(); // => expected "yes"
new ZField.foo(); // => expected "no"

我的问题是:

有没有办法实施ImAPropertyOfAnAAADerivedClass

3 个答案:

答案 0 :(得分:2)

没有。它以一种直接的方式赢得了胜利。由于ZZZ与AAA没有直接关系。一种可能的方法是从ZZZ公开一个公共对象并将BBB ref传递给它,然后检查它:

public class ZZZ
{
  public string foo() { return ImAPropertyOfAnAAADerivedClass ? "yes" : "no"; }

  bool ImAPropertyOfAnAAADerivedClass 
  {
      get { return TestForAAA is AAA; }
  }

  public object TestForAAA { get; set; }
}

虽然使用它会将BBB的ref传递给对象。

当然这会增加依赖性但有效!

答案 1 :(得分:1)

即可。你真的不能这样做。首先,类型实例永远不会知道先验哪些变量或字段引用它们,因此您无法确定任何BBB.ZField指向当前ZZZ实例。

你能得到的最接近的是:

public class ZZZ
{
    public string foo() { return ImAPropertyOfAnAAADerivedClass ? "yes" : "no"; }
    protected bool virtual ImAPropertyOfAnAAADerivedClass 
    {
        get { return false; }
    }
}

class BBB : AAA
{
    //Field of ZZZ type
    public readonly ZZZ ZField = new BBB_ZZZ();

    private class BBB_ZZZ : ZZZ
    {
        protected override bool ImAPropertyOfAnAAADerivedClass 
        {
            get { return true; }
        }
    }
}


new BBB().ZField.foo(); // "yes"
new ZZZ().foo();        // "no"

注意我已经创建了字段readonly,这意味着以后永远不能重新分配它。这样可以确保ZField未设置为ZZZ foo将返回"no"的实例。

当然,没有什么能阻止你(或其他人)实现一个违反这些语义的单独子类:

private class Fake_ZZZ : ZZZ
{
    protected override bool ImAPropertyOfAnAAADerivedClass 
    {
        get { return true; }
    }
}

new Fake_ZZZ().foo();   // "yes"

无论如何,这些语义都是笨拙和笨拙的。无论你想要用什么来完成它,都必须有更好的方法来实现它。我建议你重新考虑你的解决方案。

答案 2 :(得分:1)

处理需要知道ZZZ实例容器的最佳方法是将其注入ZZZ的构造函数。

 public class ZZZ
 { 
     public ZZZ(object owner = null)
     { 
       this.owner = owner;
     }
     readonly object owner;

     public bool ImAPropertyOfAnAAADerivedClass 
     {
         get { return owner is AAA; }
     }
 }

然后,要使您的包含类使用,请将BBB定义更改为:

 public class BBB : AAA
 {
     public BBB(){ 
        ZField = new ZZZ(this);
     }
     public readonly ZZZ ZField;
 }

此模式是dependency injection的一个非常简单的示例,可以为您提供所需的结果。