К списку форумов К списку тем
Регистрация    Правила    Главная форума    Поиск   
Имя: Пароль:
Рекомендовать в новости

С++/C#/Java - как не вызывать конструктор предка в потомке

0 - 16.06.2014 - 13:05
Всем добрый день.

Столкнулся с необходимость перенести несложный код с Pascal на какой-нибудь Си-подобный язык.

В целом, все ок, но осталась одна проблема - как я понял, в этих языках нельзя НЕ вызвать конструктор предка при создании потомка. А мне вот нужно.

Рафинированный пример того, что хочется - на Паскале.

program test ;

**$mode objfpc****$h+**

type
TBase = class
protected
x:Integer ;
flag:string ;
public
// Конструктор предка
constructor Create(Ax:Integer) ; virtual ;
procedure WriteInfo() ;
end ;

TBase2 = class(TBase)
private
public
// Перекрываем конструктор в потомке
constructor Create(Ax:Integer) ; override ;
end ;

constructor TBase.Create(Ax:Integer) ;
begin
x:=Ax ;
flag:='OK' ;
end ;

procedure TBase.WriteInfo() ;
begin
Writeln(flag,' ',x) ;
end ;

constructor TBase2.Create(Ax:Integer) ;
begin
// Если условие, то вызываем конструктор, иначе - особая инициализация
if Ax<10 then inherited Create(Ax) else x:=99 ;
end ;

begin

TBase2.Create(2).WriteInfo() ; // Здесь будет вызван конструктор предка
TBase2.Create(22).WriteInfo() ; // Здесь - уже нет

end.

Программа выводит, разумеется

ОК 2
99

ибо конструктор предка во втором случае не вызывается.

Быстрый поиск подобных вопросов показал, что для С++ это сделать невозможно. То есть, нечто вроде

class TBase2 : public TBase **
public:
TBase2(int Ax) **
TBase(Ax) ;
**
** ;

недопустимо в принципе.

Скажите, что это нельзя сделать также для С# и Java - тогда я решу проблему другим способом.

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



Гость
1 - 16.06.2014 - 16:07
А что мешает
if Ax<10 then ... else x:=99 ;
в логику базового класса перенести?
======================
А вообще, в конструкторе базового класса можно проверить реальный тип объекта и при необходимости выполнить нужный блок кода (пример на C#):
-------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
**
class Program
**
static void Main(string[] args)
**
Cbase2 v_obj = new Cbase2();
Console.WriteLine("============");
CBase v_obj2 = new CBase();
Console.ReadKey();
**
**

class CBase
**
public CBase()
**
if (!(this is Cbase2))
**
Console.WriteLine("CBase Constructor");
**
else
**
Console.WriteLine("CBase Dummy block executed");
**;
**

**

class Cbase2 : CBase
**
public Cbase2()
**
Console.WriteLine("CBase2 Constructor");
**


**
**
-------------
2 - 16.06.2014 - 16:13
Спасибо, думал об этом, но это не совсем то.

public CBase()
**
if (!(this is Cbase2))
**

Получается, что базовый класс должен знать что-то о потомке - это еще хуже для логики. А если потомков штук 10?

То, что исходная задача скорее всего возникла из-за кривой архитектуры классов - очевидно, но всё-таки, Pascal мне эту возможность прострелить ногу предоставляет. А С++, походу, нет.
Гость
3 - 16.06.2014 - 16:22
Именно "прострелить ногу". В паскале легко "забыть" про необходимость вызова базового конструктора в конструкторе потомка. И получить неполноценно инициализированный объект просто из-за забывчивости. А в сях, чтобы получить "неполноценный" объект, нужно специально писать соответсвующий код в базовом классе. Т.е. ты на 100% знаешь что делаешь.
ИМХО так...
Гость
4 - 16.06.2014 - 16:27
Паскаль дает пистолет и говорит - делай что хочешь, попадешь в ногу - сам виноват.
С дает пистолет, но при этом, чтобы выстрелить в ногу, нужно на этом пистолете осознано переключить большой красный переключатель в режим "выстрел в ногу".
5 - 16.06.2014 - 16:50
Угм, примерно так и думал. Значит, просто перепишу логику и не буду мучить С++ с Явой странными хотелками.

PS: Паскаль обычно наследует конструктор по умолчанию. В общем случае, это ещё лучше и проще, чем обязательное прописывание в С++
TBase2(int Ax) : TBase(Ax) **** ;
6 - 16.06.2014 - 21:44
В общем случае если нужно в потомке сделать особую инициализацию, то в java используется метод, который вызывается в конструкторе родителя, и по необходимости определяется в потомке, но это плохое решение.

лучшее надо смотреть от задачи.
Гость
7 - 23.06.2014 - 09:27
0-NTFS_ > Какое-то хреновое ООП =)
Проверка в родительском конструкторе на вызов для создания объекта другого класса не подойдет?

if (!this.getClass().equals(Parent.class)) ?
8 - 23.06.2014 - 11:31
7-40KHYTbIU >
Проверка в родительском конструкторе на вызов для создания объекта другого класса не подойдет?


Подойдет, конечно, но это означает, что родитель должен знать что-то о своих потомках.
Проблему решил, просто выкинул весь код с хитрым наследованием и поставил фабрику. Это заняло 10 минут кодирования и 20 минут объяснений заказчику, что это за странное колдовство с вводом нового класса :-)
Гость
9 - 24.06.2014 - 00:17
Цитата:
Сообщение от NTFS_ Посмотреть сообщение
Подойдет, конечно, но это означает, что родитель должен знать что-то о своих потомках.
Конструктор родителя может проверить класс вызвавшего объекта на равенство своему классу, пример выше.
Гость
10 - 30.06.2014 - 00:00
NTFS_,достойное решение, более чем :-) Вопрос очень интересный..А как думает уважаемое сообщество, с точки зрения ООП - это норма, зачит, в конструкторе предка инициализировать или нет базовые свойства, в зависимости от того, кого рожаем? Не сочтите за вброс, интересно мнение :-)
Гость
11 - 07.12.2015 - 18:35
ДОБАВЬ ПАРАМЕТР В КОНСТРУКТОР ..(..,bool bNeedCall=true) и иф части которой не надо вызывать. А вообще я конструкторами пользуюсь исключительно в отладочных целях, и иню-инициирую явно функциями с приставкой Born..(..)
Гость
12 - 27.01.2016 - 20:52
Цитата:
Сообщение от NTFS_ Посмотреть сообщение
Если условие, то вызываем конструктор, иначе - особая инициализация
Можно просто в потомке сделать переинициализацию, и все дела.
Цитата:
Сообщение от Гость Посмотреть сообщение
с точки зрения ООП - это норма, зачит, в конструкторе предка инициализировать или нет базовые свойства, в зависимости от того, кого рожаем?
с точки зрения ООП - за это надо на костре сжигать)
banned
13 - 30.01.2016 - 23:31
11-uxoos > Комитет по стандарту С++ не мог не знать о таком умнейшем программисте, бгг. :)


К списку вопросов
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск




Copyright ©, Все права защищены