代码之家  ›  专栏  ›  技术社区  ›  JaredBroad

用派生类型和同名C重写属性#

  •  10
  • JaredBroad  · 技术社区  · 15 年前

    我正试图用另一个同名但派生的类型重写基类中的属性。我认为它可能是由协变或仿制药引起的,但不知道该怎么做?

    以下代码获取错误:

    错误1“sun.cache”:类型必须为 匹配重写的“outerspace.cache” 成员“outerspace.cache”

    public class OuterSpace {
        public virtual OuterSpaceData Data {get; set;}
        public virtual OuterSpaceAnalysis Analysis {get; set;}
        public virtual OuterSpaceCache Cache {get; set;}
    
    
        public class OuterSpaceData {
            //Lots of basic Data Extraction routines eg
            public virtual GetData();
        }
        public class OuterSpaceAnalysis {
            //Lots of Generic Analysis on Data routines eg
            public virtual GetMean();
        }
        public class OuterSpaceCache {
            //Lots of Caches of Past Analysis Results:
            public Dictionary<AnalysisType, List<Result>> ResultCache;
        }
    }
    
    public class Sun : OuterSpace {
        public override SunData Data {get; set;}
        public override SunAnalysis Analysis {get; set;}
        public override SunCache Cache {get; set;}
    
        public SunData : OuterSpaceData {
            //Routines to specific get data from the sun eg
            public override GetData();
        }
    
        public SunAnalysis : OuterSpaceAnalysis {
            //Routines specific to analyse the sun: eg
            public double ReadTemperature();
        }
        public SunCache : OuterSpaceCache {
            //Any data cache's specific to Sun's Analysis
            public Dictionary<AnalysisType, List<Result>> TempCache;
        }
    }
    
    public class Moon : OuterSpace {} etc.
    

    对于最终结果,当我处理sun的“data”对象时,我不希望有两个数据对象(继承的&基类),但当我尝试重写属性时,它要求sun变量与基类的类型相同。如:

    Sun EarthSun = new Sun()
    EarthSun.Analyse()  //The OuterSpace Analysis Saves results to Sun Cache:
    
    //Now try use the result:
    EarthSun.Cache[0]...
    

    与此非常相似,但使用派生类型而不是字符串数组: C# Member variable overrides used by base class method

    这个答案对我来说没什么意义: How to override member of base class after inheritance in C++

    或者这意味着这是不可能的? Can I Override with derived types?

    救命!:)有什么工作吗?

    5 回复  |  直到 15 年前
        1
  •  11
  •   Stuart    15 年前

    这不可能是你想要的方式,确切地说。

    可以使用相同的名称创建“新”属性:

    public new SunData Data
    {
      get { return (SunData) base.Data; }
      set { base.Data = value; }
    }
    

    这不是完全相同的事情,但它可能和你将要得到的一样接近。

    另一种可能的方法是:

    public SunData SunData { get; set; }
    
    public override OuterSpaceData Data
    {
      get { return SunData; }
      set { SunData = (SunData)value; }
    }
    

    这种方法的优点是它确实保证了不可能在您的数据属性中放置不是Sundata的内容。缺点是您的数据属性不是强类型的,如果您希望它静态类型化为Sundata,则必须使用Sundata属性。

    有一个丑陋的方法可以让“两全其美”,代价是混淆代码,并且很难理解代码——引入一个中间派生类,该类对基类数据属性执行“密封重写”,并用新名称重定向到另一个受保护的属性,然后拥有最终派生类。添加一个“new”数据属性,然后调用中间属性。这真是一个丑陋的黑客,虽然我已经做了,但我不会推荐它。

        2
  •  7
  •   kbrimington    15 年前

    试着用仿制药来解决这个问题。以下类提供了 OuterSpace 对其参数进行约束,以强制对属性类型执行继承规则。为了清晰起见,我省略了小类型的方法。

    public class OuterSpace<TData, TAnalysis, TCache>
        where TData : OuterSpaceData
        where TAnalysis : OuterSpaceAnalysis
        where TCache : OuterSpaceCache
    {
        public virtual TData Data { get; set; }
        public virtual TAnalysis Analysis { get; set; }
        public virtual TCache Cache { get; set; }
    }
    public class OuterSpaceData { }
    public class OuterSpaceAnalysis { }
    public class OuterSpaceCache { }
    
    public class Sun : OuterSpace<SunData, SunAnalysis, SunCache>
    {
        public override SunData Data { get; set; }
        public override SunAnalysis Analysis { get; set; }
        public override SunCache Cache { get; set; }
    }
    public class SunData : OuterSpaceData { }
    public class SunAnalysis : OuterSpaceAnalysis { }
    public class SunCache : OuterSpaceCache { }
    

    这种方法的吸引力在于它允许您返回强类型属性 对这些属性的类型强制基本继承约束。这些方法是完全可重写的;但是,请注意,可能需要重写,以避免在基类实现中引发问题。

        3
  •  1
  •   CubanX    15 年前

    如果你在寻找协方差路径,类似这样的方法应该有效:

    public class OuterSpace<TCacheType> where TCacheType : OuterSpaceCache {
        public virtual OuterSpaceData Data {get; set;}
        public virtual OuterSpaceAnalysis Analysis {get; set;}
        public virtual TCacheType Cache {get; set;}
    
    
        public class OuterSpaceData {
            //Lots of basic Data Extraction routines eg
            public virtual GetData();
        }
        public class OuterSpaceAnalysis {
            //Lots of Generic Analysis on Data routines eg
            public virtual GetMean();
        }
        public class OuterSpaceCache {
            //Lots of Caches of Past Analysis Results:
            public Dictionary<AnalysisType, List<Result>> ResultCache;
        }
    }
    
    public class Sun : OuterSpace<SunCache> {
        public override SunData Data {get; set;}
        public override SunAnalysis Analysis {get; set;}
    
        public SunData : OuterSpaceData {
            //Routines to specific get data from the sun eg
            public override GetData();
        }
    
        public SunAnalysis : OuterSpaceAnalysis {
            //Routines specific to analyse the sun: eg
            public double ReadTemperature();
        }
        public SunCache : OuterSpaceCache {
            //Any data cache's specific to Sun's Analysis
            public Dictionary<AnalysisType, List<Result>> TempCache;
        }
    }
    

    公平警告,完全未编译的代码,我可能是完全错误的:)但这是对我认为你想要的东西的一个戳…

    哦,还有我 认为 这是一个.NET 4.0唯一的解决方案,我认为您不能在前面这样做,这里引入了协方差…

        4
  •  0
  •   Conrad Frix    15 年前

    如果sundata的赋值与outerspace数据兼容(继承自),则无需修改outerspace数据的类型。

        5
  •  0
  •   StuartLC    15 年前

    对于泛型不确定,但是可以通过简单的多态性实现有限的效果(假设sundata继承数据等)

    public class Sun : OuterSpace 
    {
      void SomeInitializationMethod()
      {
        Data = new SunData();
        Analysis = new SunAnalysis(); // etc
      }
    
        }
    
    // You could also make casting simpler with a generic method on the base
    public T GetData<T>()
    {
      if (Data is T)
      {
        return Data as T;
      }
      return null;
    };
    
    推荐文章