【问题标题】:Using base class and base interface in C#在 C# 中使用基类和基接口
【发布时间】:2019-08-25 23:37:46
【问题描述】:

我正在重塑一个不使用基类和基接口的整个系统。

我这样做的想法是将所有常用方法提取到基类和基接口中。
所以基本上,我们会有:

  • 实现接口ISomeClassBase的基类SomeClassBase

  • 实现ISomeClassDerived的派生类SomeClassDerived(此接口派生自ISomeClassBase

现在的问题是,我如何在派生类中实例化“_mySession”(与基类中的强制转换不同),同时保留基类中的所有方法:

public class SomeClassBase : ISomeClassBase 
{
 public IMySessionBase _mySession = MySession.Instance();

 public SomeClassBase ()
 {
   _mySession.connect();  // Needed??
 }

 public void doSomething()
 {
  _mySession.doSomething();
 }
}

public class SomeClassDerived : SomeClassBase, ISomeClassDerived  
{
 public IMySessionDerived _mySession = MySession.Instance();

 public SomeClassDerived ()
 {
  _mySession.connect();
 }

 public void doSomethingElse()
 {    
  _mySession.doSomethingElse();
 }
}

还有一点,IMySessionDerived 实现了IMySessionBase

【问题讨论】:

  • 但是SomeClassBaseSomeClassDerived 之间没有层次结构连接(它们都实现了ISomeClassBase,但都是独立的)那么问题是什么?
  • 问题是_mySession的实例化。如果我创建派生类的新实例。我不确定构造函数是否应该在基类中。还是应该?基类中的 _mySession 是否与派生类中的重铸版本相同?
  • “重铸” ? 基类 ?再次......SomeClassBaseSomeClassDerived之间没有联系
  • _mySession 在基类中有强制转换“IMySessionBase”,但在派生类中有 IMySessionDerived。
  • class SomeClassBase : ISomeClassBase class SomeClassDerived : ISomeClassDerived 你的代码中的SomeClassDerived 不是从SomeClassBase 派生的

标签: c# inheritance interface multiple-inheritance


【解决方案1】:

不要重新定义_mySession 让它来自基类。 但是在您的派生类中,您仍然可以重新分配。

public class SomeClassDerived : SomeClassBase, ISomeClassDerived  
{
 public SomeClassDerived ()
 {
  _mySession = MySession.Instance(); //Declaration comes from base class automatically
  _mySession.connect();
 }

 public void doSomethingElse()
 {    
  _mySession.doSomethingElse();
 }
}

如果您的 IMySessionBaseIMySessionDerived 遵循层次结构,它应该可以工作。但在极少数情况下,您最终可能会遇到 DoubleDispatchProblem。

正如评论中指出的那样,如果您想从IMySessionDerived 做某事,您可以添加一个属性。

public class SomeClassDerived : SomeClassBase, ISomeClassDerived  
{
    IMySessionDerived _derivedSessionAccessor=>  _mySession as IMySessionDerived;

}

更新:为了解决此处的确切设计问题,

不是从基类派生,而是将其作为一个字段。并从接口继承。所以不要做上述方法,

喜欢,

public class SomeClassBase : ISomeClassBase 
{
 public IMySessionBase _mySession ;
 public SomeClassBase ( IMySessionBase session)
 {
   _mySession=session;
   _mySession.connect();  // Needed??
 }

 public void doSomething()
 {
  _mySession.doSomething();
 }
}

 public class SomeClassDerived : , ISomeClassDerived  
{
 public IMySessionDerived _mySession = MySession.Instance();
 private SomeClassBase _baseClassInstance;
 public SomeClassDerived ()
 {
   _baseClassInstance=new SomeClassBase(_mySession);
    //_mySession.connect();
 }

 public void doSomethingElse()
 {    
  _baseClassInstance.doSomethingElse();
 }
}

【讨论】:

  • 但如果doSomethingElse 来自IMySessionDerivedIMySessionBase,则您不能致电_mySession.doSomethingElse();
  • 是的,没错,但是您可以在派生类中进行类型转换。整个设计违反了里氏替换原则。但它仍然适合 OP 场景。
  • @Selvin,你是对的,这正是我要解决的问题!
  • @Code Name Jack,你是说这是一种不好的方法吗?那你会怎么设计呢?
  • 在这些情况下,优先组合而不是继承,实现接口但不要从基类继承,我会在我的答案中添加它
【解决方案2】:

粘贴@Selvin 答案而不是隐藏在 cmets 中的链接:
这里的技巧是使用关键字“base()”

using System;
using System.Runtime.CompilerServices;

public class Program
{
    public static void Main()
    {
        var o1 = new O1();
        o1.DS1();
        var o2 = new O2();
        o2.DS1();
        o2.DS2();
    }

    public class Session1
    {
        protected readonly Type ownerType;
        public Session1(Type type)
        {
            ownerType = type;
        }

        public virtual void DS1([CallerMemberName] string functionName = "")
        {
            Console.WriteLine(ownerType.Name + ":" +  GetType().Name + ":" + functionName);
        }       
    }

    public class Session2 : Session1
    {
        public Session2(Type type):base(type) { }

        public virtual void DS2([CallerMemberName] string functionName = "")
        {
            Console.WriteLine(ownerType.Name + ":" +  GetType().Name + ":" + functionName);
        }   
    }

    public class O1
    {
        private readonly Session1 t;

        public O1() : this(new Session1(typeof(O1))) { }
        protected O1(Session1 t)
        {
            this.t = t;
        }
        public void DS1()
        {
            t.DS1();
        }
    }

    public class O2 : O1
    {
        private readonly Session2 t;

        public O2() : this(new Session2(typeof(O2))) { }
        protected O2(Session2 t) : base(t)
        {
            this.t = t;
        }

        public void DS2()
        {
            t.DS2();
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-08
    • 2014-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-01
    • 2017-12-29
    • 1970-01-01
    相关资源
    最近更新 更多