родительский класс не может видеть дочерние параметры - PullRequest
0 голосов
/ 08 июля 2019

я отредактировал вопрос, чтобы быть более понятным. старый вопрос ниже.

У меня есть 2 дочерних класса с собственной реализацией клиента базы данных, но все еще с тем же интерфейсом родительской базы данных (т. Е. Таким как шаблон репозитория).

class Child1
{
  protected IDB_Child1 DB;
  public void Disconnect()
  {
    DB.disconnect();
  }
}
class Child2
{
  protected IDB_Child2 DB;
  public void Disconnect()
  {
    DB.Disconnect();
  }
}
interface IDB_Child1 : IDB {}
interface IDB_Child2 : IDB {}
interface IDB { void Disconnect() }

это работает:

Child1 c1 = new Child1();
c1.Disconnect(); //OK

очевидно, что я хочу перенести общую функциональность, описанную выше, на родителя, как самый базовый шаг рефакторинга. я делаю:

abstract class Parent
{
  protected IDB DB;
  public void Disconnect()
  {
    DB.Disconnect();
  }
}

class Child1 : Parent
{
  protected IDB_Child1 DB;
}
class Child2 : Parent
{
  protected IDB_Child2 DB;
}

по какой-то причине C # имеет собственную область видимости для таких переменных, и я не могу получить доступ к БД из родительского класса:

Child1 c1 = new Child1();
c1.Disconnect(); // ERROR: DB is null in the parent even though in the c1 it is initialized and visible from child1 class methods.

как мне добиться такой базовой функциональности ООП?

Ответы [ 2 ]

1 голос
/ 08 июля 2019

Похоже, что дженерики могут дать вам то, что вы хотите (при условии, что IDB_Child расширяет или реализует IDB):

abstract class Parent<T>
{
  protected T DB;
  public void Disconnect()
  {
    DB.Disconnect();
  }
}

class Child1 : Parent<IDB_Child1>
{
}
class Child2 : Parent<IDB_Child2>
{
}

Вы также можете использовать метод доступа вместо наследования поля:

abstract class Parent
{
  protected IDB DB() {get;}
  public void Disconnect()
  {
    getDB().Disconnect();
  }
}

class Child1 : Parent
{
  protected IDB_Child1 _DB;
  override IDB DB() 
  {  
      get 
      {
          return DB;
      }
  }
}
class Child2 : Parent
{
  protected IDB_Child2 _DB;
  override IDB DB() 
  {  
      get 
      {
          return DB;
      }
  }
}

// ОШИБКА: DB является нулем в родительском элементе, хотя в c1 она инициализирована и видима из методов класса child1

Это потому, что вы объявили (но не инициализировали то, что показали) поле new DB в дочерних классах. Поскольку родительский экземпляр DB виден дочерним элементам, вам не нужно объявлять другой.

1 голос
/ 08 июля 2019

Вам не нужно объявлять DB в дочернем (вы можете получить доступ к одному из Parent по наследству). В качестве подсказки вы должны были использовать новое ключевое слово, потому что оно конфликтовало с родительским полем БД (что обычно очень плохо).

Просто удалите

новая защищенная БД IDB_Child;

Вот полная реализация:

public interface IDB
{
    void Bar();
}

abstract class Parent 
{
    protected IDB DB;
    public Parent(IDB database) {
        DB = database;
    }
    public void Foo()
    {
        DB.Bar();
    }
}
class Child : Parent
{
    public Child(IDBImplem database) : base(database) {}
    public void ChildFoo()
    {
        DB.Bar();
    }
}

public class IDBImplem : IDB
{
    public void Bar()
    {
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...