Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Доступ к членам производных классов  (Прочитано 8302 раз)
0 Пользователей и 1 Гость смотрят эту тему.
MasterMan342
Участник

ru
Offline Offline
Пол: Мужской

« : 21-11-2012 20:09 » 

Доброе время суток!

Подскажите как получить информацию о производных классах (B, C, D), базового класса A
а потом изменить их значение...

Ну к примеру:

Код:
public class A
    {
        public A()
        {
            //Как мне из конструктора базового класса а узнать о наследуемых его классах
            //Т.Е. к примеру получить массив Type[]
            //Если это можно сделать рефлексией, то ткните меня носом в нужный метод! я все обыскал...
        }
    }

    class B : A
    {
        public static void Call()
        {

        }
    }

Что с этим можно сделать:
Я пытаюсь узнать, есть ли в произвольных классах класса А метод Call, и если он есть то вызвать его...
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #1 : 21-11-2012 20:40 » 

А если сделать наследованием? Правда при наследовании, в конструкторе родительского класса нельзя вызывать методы дочерних классов. Будут вызываться методы самого родительского класса.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Dale
Блюзмен
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #2 : 21-11-2012 21:07 » 

Подскажите как получить информацию о производных классах (B, C, D), базового класса A

Никак. Базовый класс ничего не знает о производных, это один из базовых принципов ООП.

Можно попробовать применить очень кривой костыль - средствами рефлексии перебрать все классы в пределах сборки и выяснить, какие из них насдедуют A непосредственно либо косвенно. Но при этом следует учесть, что производные классы могут вообще располагаться в других сборках.

а потом изменить их значение...
Для начала, в чем состоит смысл фразы "изменить значение классов"?


Вообще рефлексия - весьма тонкое средство. Если она применяется в проекте, возможен один из двух вариантов: либо хороший программист делает полезный обобщенный  инструментарий (вроде системы автоматизированного тестирования или генератора мок-объектов), либо плохой пытается решить относительно простую задачу извращенным способом.
Записан

Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.

Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard

Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #3 : 21-11-2012 22:23 » 

MasterMan342, вообще такая задача решается несколько иначе: в классе A объявляется абстрактный метод Call, а потомки его реализуют (кому не надо, оставляют пустым). (Отсылка к шаблону проектирования Template Method.)

Однако из конструктора предка не вызвать реализацию потомков по той причине, что когда срабатывает конструктор предка, конструктор потомка ещё не сработал, и таблица виртуальных методов ещё не заполнена. Но, к счастью, именно для абстрактных методов такого ограничения нет. Поэтому

Код: (C#)
abstract class A
{
  public A()
  {
    this.F();
  }
  public abstract void F();
}

class B : A
{
  public override void F()
  {
    Console.WriteLine("B.F");
  }
}

A a = new B(); // B.F
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Dmitry
Помогающий

ru
Offline Offline

« Ответ #4 : 22-11-2012 11:00 » new

Однако из конструктора предка не вызвать реализацию потомков по той причине, что когда срабатывает конструктор предка, конструктор потомка ещё не сработал, и таблица виртуальных методов ещё не заполнена.
Таблица в.м. строится при IL компиляции, когда для каждого нового типа создаётся экземпляр Type, в составе которого и находится таблица. А вызывать в.м. из конструктора базового класса не рекомендуется, потому что может быть вызвана реализация этого метода производного класса. А т.к. конструктор производного класса ещё не сработал, т.е. объект полностью ещё не инициализировался, то поведение будет непредсказуемым.
« Последнее редактирование: 22-11-2012 11:03 от Dmitry » Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #5 : 22-11-2012 13:03 » 

Цитата: Dmitry
А т.к. конструктор производного класса ещё не сработал, т.е. объект полностью ещё не инициализировался, то поведение будет непредсказуемым.
Согласен.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
MasterMan342
Участник

ru
Offline Offline
Пол: Мужской

« Ответ #6 : 22-11-2012 15:02 » 

MasterMan342, вообще такая задача решается несколько иначе: в классе A объявляется абстрактный метод Call, а потомки его реализуют (кому не надо, оставляют пустым). (Отсылка к шаблону проектирования Template Method.)

Однако из конструктора предка не вызвать реализацию потомков по той причине, что когда срабатывает конструктор предка, конструктор потомка ещё не сработал, и таблица виртуальных методов ещё не заполнена. Но, к счастью, именно для абстрактных методов такого ограничения нет. Поэтому

Код: (C#)
abstract class A
{
  public A()
  {
    this.F();
  }
  public abstract void F();
}

class B : A
{
  public override void F()
  {
    Console.WriteLine("B.F");
  }
}

A a = new B(); // B.F

Все это я отлично понимаю, и про базовый принцип ООП тоже знаю... но ведь рефлексия нарушает инкапсуляцию, а значит я думал и этот закон можно как-то обойти Улыбаюсь Нельзя значит нельзя...
Через переопределение виртуальных методом - не то что я хотел))
Ну а так, в этом вопросе нет особого смысла как и в том, что я пытался "изобразить")

Тема закрыта!
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines