none
C#, объявление и инициализация подкласса RRS feed

  • Вопрос

  • Сразу напишу вот такое: то, что меня интересует - я нашёл на MSDN, но разобраться не смог, поэтому пришёл сюда. А ещё я не очень хорошо разбираюсь в объектно-ориентированном программировании: с классами работать умею, а вот с подклассами туго.

    Суть проблемы в следующем ...

    Допустим у меня есть класс:

    class Alpha
    {
    	public Alpha()
    	{
    	}
    	// какой нибудь более продуктивный конструктор, с параметрами
    	// набор данных, свойств, функций
    }

    И есть следующий подкласс:

    class Beta:Alpha
    {
    	// конструкторы, данные, свойства, методы
    }

    Я не случайно описал в базовом классе пустой конструктор без параметров: дело в том, что без этого конструктора объявление конструктора подкласса не допускается с ошибкой: "Form1.Alpha" не содержит конструктор, который принимает аргументы "0".

    Далее мне нужно объявить экземпляр класса Alpha:

    Alpha baseinstance;

    А теперь главная беда: объявление экземпляра подкласса Beta с наследованием всех данных экземпляра базового класса Alpha; то есть:

    Beta subinstance;

    Мне нужно, что бы из subinstance были видны все (protected) данные, сохранённые в baseinstance.

    На деле же я получаю вот что: при объявлении экземпляра Beta вызывается пустой конструктор класса Alpha, то есть подкласс объявляет себе собственный новый базовый класс.

    Я знаю в чём проблема: проблема в том, что я не знаю, как правильно объявлять подкласс при условии, что базовый класс уже имеется.

    Что я хочу узнать: как правильно объявлять подкласс при условии, что базовый класс (с нужным мне набором данных) уже имеется ?

    23 февраля 2015 г. 18:38

Ответы

  • Объект не наследует другой объект. Наследуются типы данных. Собака - наследник животного, но пудель - не наследник куропатки, хотя птица - тоже животное. Такой вот парадокс ООП :)

    Если сообщение помогло Вам, пожалуйста, не забудьте отметить его как ответ данной темы. Удачи в программировании!

    • Помечено в качестве ответа programmist_0 25 февраля 2015 г. 12:16
    24 февраля 2015 г. 14:09
  • Пудель Шарик не может быть наследником попугая Гоши. Хотя их типы (собака и птица) - наследники одного класса животного. Что не понятного? Вы пытаетесь применить наследование там, где требуется нечто другое.

    Если сообщение помогло Вам, пожалуйста, не забудьте отметить его как ответ данной темы. Удачи в программировании!

    • Помечено в качестве ответа programmist_0 25 февраля 2015 г. 12:16
    24 февраля 2015 г. 14:44
  • Вот смотрите, у вас есть 4 объекта гамма. Три объекта бетта, и два объекта альфа. Два объекта гамма пользуются своими бетта, два обекта одним бетта. Ну и бетты, одна смотрит на свою альфу и две на вторую альфу. Как то так:

    Если картинка такая именно на уровне объектов, то вам нужно не наследование, а включение.

    • Помечено в качестве ответа programmist_0 25 февраля 2015 г. 12:16
    24 февраля 2015 г. 14:39
    Отвечающий
  • Да, вы абсолютно правы. Я бы в бетте объявил свойство типа альфа, в гамме типа бетта. Ну и у классов альфа и бетта, я бы сделал метод для создания его подчиненных бетта и гамма соответственно.

    То есть по коду должно быть нечто такое:

    class Alpha
    {
    	Beta[] inherits;
    }
    
    class Beta
    {
    	Alpha parent;
    	Gamma[] inherits;
    }
    
    class Gamma
    {
    	Beta parent;
    }

    Если так, то что делать с методами, которые должны быть описаны в Alpha, и доступны в Beta и Gamma ?

    • Помечено в качестве ответа programmist_0 25 февраля 2015 г. 12:17
    24 февраля 2015 г. 20:41

Все ответы

  • Ваши оба объекта разные, вы имеете дело с двумя разными экземплярами объектов. Чтобы добиться того, что вы хотите нужно поочерёдно скопировать значения из одного объекта в другой. По другому связать их не получится.

    Сделаем содержимое сообщества лучше, вместе!

    23 февраля 2015 г. 19:24
    Модератор
  • Можете мне объяснить пожалуйста, как это сделать ? На MSDN много кода, а из того что я понял - это объявление базового класса.

    Только если делать через пятницу - сначала объявлять подкласс, а потом заполнять поля базового класса, сделанные доступными через base (но это нарушение правил, из того, что помню по теории).

    23 февраля 2015 г. 19:31
  • Я не случайно описал в базовом классе пустой конструктор без параметров: дело в том, что без этого конструктора объявление конструктора подкласса не допускается с ошибкой: "Form1.Alpha" не содержит конструктор, который принимает аргументы "0".
    У многих классов нет пустых конструкторов, но это не мешает им иметь подклассы.
    class Alpha {
        public Alpha(int i) { }
    }
    class Beta:Alpha {
        public Beta(int i,int j):base(i+j) { }
    }
    24 февраля 2015 г. 2:52
  • Добрый день.

    Самый главный вопрос, какая у вас цель? Сколько объектов вам нужно в программе? Если один, то создаете его на основе потомка, а там где вам нужно использовать его как базовый, вы это можете нормально делать. Вот этот код компилируется и работает:

    Beta b = new Beta();
    Alpha a = b;

    Если объектов нужно в памяти два, то тогда поступайте как вам посоветовал Yatajga, реализуйте копирование полей из одного объекта в другой. Это можно сделать, например, просто присваивая свойства одного объекта другому. Я бы этот метод сделал в базовом классе, он бы принмал один параметр типа базовый класс и возвращал базовый класс, ну и имел бы вид:

    public Alpha CreateCopy(Alpha a)
    {
        Alpha result = new Alpha();
        // Копируем поля
        result._field1 = a._field1;
        result._field2 = a._field2;
        return result;
    }

    P.s. Коллега, на всякий пожарный, вы понимаете разницу между классом, объектом и объектной переменной?
    24 февраля 2015 г. 6:03
    Отвечающий

  • P.s. Коллега, на всякий пожарный, вы понимаете разницу между классом, объектом и объектной переменной?

    Класс - тип данных; объект - некая сущность, созданная и хранимая в памяти.

    Про объектную переменную ничего не могу сказать (но по идее это ссылка на объект).

    По моему вопросу: у меня должен быть один объект класса Alpha, много объектов класса Beta, наследуемых от объекта класса Alpha. А ещё у меня должен быть третий подкласс - Gamma:Beta. И от одного Beta должно наследоваться ещё несколько объектов класса Gamma.

    В итоге должна получиться древовидная структура данных, построенная на классах и наследовании. Более того - мне нужна будет ротация объектов: объекты класса Gamma должны уметь пере-создаваться у других родителей-Beta (но это будет не проблема, когда я смогу всё изначально правильно оформить).


    • Изменено programmist_0 24 февраля 2015 г. 10:35
    24 февраля 2015 г. 10:34
  • Хм, что-то у вас как-то все сложно. А вы уверены, что вам нужно именно наследование, а не включение. У ваших бета, данные характерные для альфа, должны быть одни на всех? Или у каждого свой набор со своими значениями?
    24 февраля 2015 г. 11:33
    Отвечающий
  • Объект не наследует другой объект. Наследуются типы данных. Собака - наследник животного, но пудель - не наследник куропатки, хотя птица - тоже животное. Такой вот парадокс ООП :)

    Если сообщение помогло Вам, пожалуйста, не забудьте отметить его как ответ данной темы. Удачи в программировании!

    • Помечено в качестве ответа programmist_0 25 февраля 2015 г. 12:16
    24 февраля 2015 г. 14:09
  • Хм, что-то у вас как-то все сложно. А вы уверены, что вам нужно именно наследование, а не включение. У ваших бета, данные характерные для альфа, должны быть одни на всех? Или у каждого свой набор со своими значениями?

    Есть набор данных, который должен идентифицировать объект:

    для Gamma есть собственный идентификатор + доступ к идентификатору родителя-Beta;

    так же для объекта Beta - собственный идентификатор + идентификатор родителя-Alpha;

    и у объекта Alpha должен быть всем идентификаторам идентификатор.


    • Изменено programmist_0 24 февраля 2015 г. 14:35
    24 февраля 2015 г. 14:32
  • Объект не наследует другой объект. Наследуются типы данных. Собака - наследник животного, но пудель - не наследник куропатки, хотя птица - тоже животное. Такой вот парадокс ООП :)

    Если сообщение помогло Вам, пожалуйста, не забудьте отметить его как ответ данной темы. Удачи в программировании!

    Простите, я вашего примера не понял.
    24 февраля 2015 г. 14:34
  • Вот смотрите, у вас есть 4 объекта гамма. Три объекта бетта, и два объекта альфа. Два объекта гамма пользуются своими бетта, два обекта одним бетта. Ну и бетты, одна смотрит на свою альфу и две на вторую альфу. Как то так:

    Если картинка такая именно на уровне объектов, то вам нужно не наследование, а включение.

    • Помечено в качестве ответа programmist_0 25 февраля 2015 г. 12:16
    24 февраля 2015 г. 14:39
    Отвечающий
  • Пудель Шарик не может быть наследником попугая Гоши. Хотя их типы (собака и птица) - наследники одного класса животного. Что не понятного? Вы пытаетесь применить наследование там, где требуется нечто другое.

    Если сообщение помогло Вам, пожалуйста, не забудьте отметить его как ответ данной темы. Удачи в программировании!

    • Помечено в качестве ответа programmist_0 25 февраля 2015 г. 12:16
    24 февраля 2015 г. 14:44

  • Если картинка такая именно на уровне объектов, то вам нужно не наследование, а включение.

    Ну хорошо, тогда объясните мне, что это за включение, и как его реализовать в моём случае ?

    Я понимаю, что есть какой нибудь идентификатор объекта класса Alpha, и он должен быть protected (аля наследование), что бы Beta и Gamma "знали", за кем они подвешены.

    Ну а так - картинка правильная. Можно сравнивать с иерархией подчинения (на работе, или в армии):

    Alpha - начальник;

    Beta - руководитель отдела;

    Gamma - сотрудник.

    Схема подчинения соответствующая.



    • Изменено programmist_0 24 февраля 2015 г. 19:01
    24 февраля 2015 г. 18:57
  • Да, вы абсолютно правы. Я бы в бетте объявил свойство типа альфа, в гамме типа бетта. Ну и у классов альфа и бетта, я бы сделал метод для создания его подчиненных бетта и гамма соответственно.
    24 февраля 2015 г. 19:46
    Отвечающий
  • Да, вы абсолютно правы. Я бы в бетте объявил свойство типа альфа, в гамме типа бетта. Ну и у классов альфа и бетта, я бы сделал метод для создания его подчиненных бетта и гамма соответственно.

    То есть по коду должно быть нечто такое:

    class Alpha
    {
    	Beta[] inherits;
    }
    
    class Beta
    {
    	Alpha parent;
    	Gamma[] inherits;
    }
    
    class Gamma
    {
    	Beta parent;
    }

    Если так, то что делать с методами, которые должны быть описаны в Alpha, и доступны в Beta и Gamma ?

    • Помечено в качестве ответа programmist_0 25 февраля 2015 г. 12:17
    24 февраля 2015 г. 20:41
  • И кто вам мешает их вызывать? Если не устраивает public, объявите их internal и за пределами вашей сборки, теоретически, никто к ним доступ не получит...
    25 февраля 2015 г. 5:28
    Отвечающий