Использование базового класса и базового интерфейса в C # - PullRequest
0 голосов
/ 04 апреля 2019

Я изменяю всю систему, которая не использует базовые классы и базовые интерфейсы.

Моя идея состоит в том, чтобы извлечь все распространенные методы в базовые классы и базовые интерфейсы.
Таким образом, в основном, мы будем иметь:

  • Базовый класс SomeClassBase, реализующий интерфейс ISomeClassBase

  • Производный класс SomeClassDerived, реализующий ISomeClassDerived (этот интерфейс является производным от 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.

Ответы [ 2 ]

1 голос
/ 04 апреля 2019

Вставка ответа @Selvin вместо ссылки, спрятанной в комментариях:
Хитрость заключается в том, чтобы использовать ключевое слово "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();
        }
    }
}
0 голосов
/ 04 апреля 2019

Не переопределять _mySession Пусть оно исходит из базового класса.Однако в вашем производном классе вы все равно можете переназначить.

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

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

Если ваши IMySessionBase и IMySessionDerived следуют иерархии, это должно работать.Но в некоторых редких случаях вы можете столкнуться с проблемой 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();
 }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...