Перейти к содержимому

Фотография

Кто и где лучший программист?Кто они лучшие и как их определить?


  • Авторизуйтесь для ответа в теме
Сообщений в теме: 220

#81
dostalker

dostalker
  • Частый гость
  • 86 сообщений
2v04bvs: разницы между Sleep и sleep заказчик не заметит :-D мне подумалось, что тут тоже мало кто заметит, да и пофлеймить чет хотелось...

2all (и особенно 2 Visual1 - как любителю всяческих задач): квадрат... параллелограм... гы! ООП - это конечно типа того, а вот нарисовать извлечения корня 3-ей степени на R-языке?
Синтаксис R-языка прост! Имеем N регистров R0..RN Регистр хранит натуральное число. И, собственно, язык:
0. 1 строка = 1 команда, строки нумерованы, начальные данные закидываются в регистры, затем запили, закусили и поехали!
1. команда: Ri присвоить 0
2. команда: Ri увеличить на 1
3. безусловный переход на строку x
4. условный переход: если Ri=Rj то строка x иначе следующая строка

кто не справился - я не виноват :laugh:
  • 0

#82
Visual1

Visual1
  • В доску свой
  • 1 198 сообщений

2v04bvs: разницы между Sleep и sleep заказчик не заметит :-D мне подумалось, что тут тоже мало кто заметит, да и пофлеймить чет хотелось...

Там не только Sleep и sleep было, еще и несуществующий тип VOID был вместо void. На самом деле все всё заметили, просто по доброте душевной промолчали... :laugh:

2all (и особенно 2 Visual1 - как любителю всяческих задач): квадрат... параллелограм... гы! ООП - это конечно типа того, а вот нарисовать извлечения корня 3-ей степени на R-языке?
Синтаксис R-языка прост! Имеем N регистров R0..RN Регистр хранит натуральное число [skipped...]

Конкретное решение здесь привести не получится, но вот идея, которая представляется мне подходящей. Применить итеративный метод касательных, что-то вроде метода Ньютона-Рафсона. Задается желаемая погрешность вычислений, а уравнение нелинейной функции в некоторой произвольной начальной точке заменяется уравнением прямой, касательной к графику функции в этой точке. Затем ищется следующая точка, в ней проводится касательная, вычисляется значение прямой в этой точке и разность между найденным последующим и предыдущим значением. Процесс продолжается, пока разность не будет меньше заданной погрешности. Сходимость метода достаточно быстрая.

Сообщение отредактировал Visual1: 22.08.2006, 22:32:45

  • 0

#83
yedyge

yedyge
  • Свой человек
  • 879 сообщений


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

1. "Чудесны" или не очень - кому как нравится, дело личного вкуса. :D
2. "Временами" справедливы? А временами, значит, нет? Потрудитесь указать, где несправедливы и обосновать, почему. :D
3. Насчет универсальности - я на нее не претендовал и обеспечить ее не обещал. :lol:

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


опровергаю:

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

Неужели такие простые вещи все еще нужно обосновывать? :lol: Ширина и высота - это данные каждого объекта (экземпляра класса) прямоугольника. Если их не скрывать, сделать открытыми (т.е. public - доступными для любых обращений к ним извне), тогда вообще о каком ООП можно говорить?

я не говорю об области видимости double width, height. я говорю о возможности программисту изменять эти значения, хучь методами, хучь пропертиями. вы ведь согласны с тем, что _понятия_ габаритов НЕ должны быть закатаны в тройной блиндаж подальше от пользователя (прикладного программера)?
или для вас всё таки просто и очевидно закрыть всякий доступ (опосредованный и прямой) к габаритам четырёхугольника?


а вот прямоугольнику придётся переписывать почти все методы (может быть кроме деструктора) квадрата напрочь, потому, что нужно разорвать эквивалентность высоты и ширины в каждом методе. а это существенный гемор :D

Гимор, причем существенный, обеспечен в любом случае. :laugh: Оба способа (квадрат из прямоугольника или прямоугольник из квадрата) с точки зрения программиста вполне законны и имеют право на существование. Возможно, придется и в самом деле пойти привычным путем и создавать класс квадрата, наследуя его из класса прямоугольника. Но опять же, в таком случае придется принимать специальные меры, чтобы производный класс вел себя как базовый. Базовый класс всегда определяет свойства и поведение своих производных классов, разве не так? Соответственно, производный класс всегда должен наследовать все свойства и поведение своего базового класса и плюс добавлять к ним еще какие-то свои собственные, присущие только ему, свойства и методы. Другими словами, объекты производных классов всегда должны обеспечивать возможность их работы в качестве объектов своих базовых классов. В случае с квадратом и прямоугольником этого нет - мы не можем просто работать с квадратом, как с объектом его базового класса - прямоугольника.

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

мои симпатии в общем случае сводятся к такому наследованию:
четырёхугольник := многоугольник
паралеллограмм := четырёхугольник
прямоугольник := паралеллограмм
ромб := паралеллограмм
квадрат := ромб, прямоугольник

но, в который раз повторяю, что война план покажет.
  • 0

#84
Visual1

Visual1
  • В доску свой
  • 1 198 сообщений

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

Объяснение не принимается, в нем нет логики. Если имеется мое утверждение "на универсальность не претендовал", то из него никак не следует, что мои остальные утверждения "временами несправедливы". Они справедливы в рамках принятых моделей и допущений. Ну да ладно. У нас есть кое-что поважнее, на чем надо сосредоточить внимание - квадрат и пямоугольник!

я не говорю об области видимости double width, height. я говорю о возможности программисту изменять эти значения, хучь методами, хучь пропертиями. вы ведь согласны с тем, что _понятия_ габаритов НЕ должны быть закатаны в тройной блиндаж подальше от пользователя (прикладного программера)?
или для вас всё таки просто и очевидно закрыть всякий доступ (опосредованный и прямой) к габаритам четырёхугольника?

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

Кстати, доступ к свойствам (properties) фактически реализован в виде методов. В С++ это очевидно, а в VB возможны некоторые заблуждения, из-за обманчиво простого внешнего вида выражений. Но все равно, если вы в программе на VB обращаетесь к свойству (например, a = rectangle.width), то на самом деле все же происходит вызов метода (процедуры) Property Get width этого объекта, а не прямой доступ к его данным (width) из программы.

мои симпатии в общем случае сводятся к такому наследованию:
четырёхугольник := многоугольник
паралеллограмм := четырёхугольник
прямоугольник := паралеллограмм
ромб := паралеллограмм
квадрат := ромб, прямоугольник

но, в который раз повторяю, что война план покажет.

Отлично! Вы сделали свой выбор. Если "война план покажет", тогда довольно слов - к оружию! :smoke: (Я имею в виду, к прямому кодированию). В соответствии с Вашими симпатиями, предлагаю Вам запроектировать базовый класс прямоугольник, затем - производный от него класс квадрат (с четырехугольника начинать не будем, чтобы не усложнять, а то ведь так можно начать вообще с абстрактной "произвольной геометрической фигуры"). Готов всячески помогать Вам. Вот, например, базовый класс прямоугольника:
class Rectangle
{
private:
double Width;
double Height;

public:
void SetWidth(double w) {Width=w;}
void SetHeight(double h) {Height=h;}
double GetHeight() const {return Height;}
double GetWidth() const {return Width;}
};

Конструктор и деструктор, для простоты не приводятся (принимаются по умолчанию). Самое главное здесь, что я утверждаю и на чем настаиваю:
Можно получить квадрат и его базовый класс прямоугольник, и это будут два полностью корректных, логически непротиворечивых класса, соответствующих правилам наследования, и полностью пригодных для использования. Не трудно сделать, чтобы в квадрате оба метода SetWidth и SetHeight устанавливали, а GetHeight и GetWidth - возвращали одинаковые значения, как это и полагается для квадрата. Но даже и в этом случае, клиентская программа все равно будет работать некорректно.

Сообщение отредактировал Visual1: 24.08.2006, 11:18:47

  • 0

#85
yedyge

yedyge
  • Свой человек
  • 879 сообщений

Объяснение не принимается, в нем нет логики. Если имеется мое утверждение "на универсальность не претендовал", то из него никак не следует, что мои остальные утверждения "временами несправедливы".

я вам по секрету расскажу, что таки следует.

Они справедливы в рамках принятых моделей и допущений.

это более подробное раскрытие фразы "на универсальность не претендовал". иногда может потребоваться уточнить что точно "принято" за модели и допущения, чтобы чётко понимать, когда именно "утверждения временами несправедливы"(или неприменимы).


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

разницы не вижу. на примитивном примере прямоугольника вся информационная ёмкость рассматриваемого объекта по сути должна быть доступна снаружи. тут нет семафоров всяких или дескрипторов ошибки или открытых потоков, которые кому нибудь когда нибудь в какой нибудь ситуации могут понадобиться, причём как private или protected.

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

Ну да ладно. У нас есть кое-что поважнее, на чем надо сосредоточить внимание - квадрат и пямоугольник! <...> Можно получить квадрат и его базовый класс прямоугольник<...> Но даже и в этом случае, клиентская программа все равно будет работать некорректно.

"в общем случае некорректно" или "можно привести ситуацию, в которой некорректно"?
  • 0

#86
Visual1

Visual1
  • В доску свой
  • 1 198 сообщений


Объяснение не принимается, в нем нет логики. Если имеется мое утверждение "на универсальность не претендовал", то из него никак не следует, что мои остальные утверждения "временами несправедливы".

я вам по секрету расскажу, что таки следует.

Не надо мне "по секрету". Здесь открытое обсуждение. И вообще, меня это уже не интересует.

<...>и ваши намерения как применить это в дальнейшем наверняка не совпадут с моими намерениями. и мысли о поведении своих классов в руках дальнейших программистов-пользователей наших классов неприложимы.

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

Вы свои предпочтения ("симпатии", как Вы сказали) уже четко назвали. Следуя им, я Вам предложил базовый класс прямоугольника Rectangle. Он Вас устраивает? С Вашими намерениями совпадает? Если нет, то почему? А если да, то разработайте, пожалуйста, класс Square для квадрата, производный от Rectangle. Если по каким-то причинам не можете (например, нет времени, возможности и т.д.), тогда я сделаю это (ведь я обещал помогать Вам).

"в общем случае некорректно" или "можно привести ситуацию, в которой некорректно"?

Вам прямо сразу все вынь да положь, на тарелочке. :smoke: Сами же сказали: "война план покажет". :rotate: Вот я и предлагаю действовать (см. выше).
  • 0

#87
yedyge

yedyge
  • Свой человек
  • 879 сообщений
я бы сделал так
class Rectangle
{
private:
	double Width;
	double Height;
public:
	virtual void SetWidth(double dW) { Width = dW; };
	virtual void SetHeight(double dH) { Height = dH; };
	virtual double GetHeight() const { return Height; };
	virtual double GetWidth() const { return Width; };
};

class Square : public Rectangle
{
public:
	virtual void SetWidth(double dW)
	{
		this->Rectangle::SetWidth(dW);
		this->Rectangle::SetHeight(dW);
	};
	virtual void SetHeight(double dH)
	{
		this->Rectangle::SetWidth(dH);
		this->Rectangle::SetHeight(dH);
	};
};
честно признаюсь, что Get виртуальный на всякий случай. то есть на момент я не соображу зачем собственно. просто нутром предполагаю.

а так кроме установки эквивалентности высоты ширине (ровно два метода) больше ничего интересного в квадрате делать не надо - всё необходимое уже есть в прямоугольнике.
  • 0

#88
Visual1

Visual1
  • В доску свой
  • 1 198 сообщений
Идея сделать функции SetWidth и SetHeight виртуальными совершенно правильная. :D Без этого не обойтись, поскольку мы собираемся их переопределить в классе Square.
А функции группы Get делать виртуальными нет никакой необходимости - любая из них все равно будет возвращать для квадрата одно и то же значение, поскольку это значение будет обеспечено установочными функциями Set. Вполне можно обойтись вызовом функций Get базового класса Rectangle.

Итак, приходим к следующей иерархии классов:
class Rectangle
{
private:
double Height;
double Width;

public:
virtual void SetWidth(double dW) {Width=dW;}
virtual void SetHeight(double dH) {Height=dH;}
double GetHeight() const {return Height;}
double GetWidth() const {return Width;}
};

class Square : public Rectangle
{
public:
virtual void SetWidth(double dW);
virtual void SetHeight(double dH);
};
В производном классе реализуем функции так, чтобы обеспечить правильное поведение квадрата при изменении любого из его размеров:

void Square::SetWidth(double dW)
{
Rectangle::SetWidth(dW);
Rectangle::SetHeight(dW);
}
void Square::SetHeight(double dH)
{
Rectangle::SetHeight(dH);
Rectangle::SetWidth(dH);
}
Предложенные улучшения незначительны и не принципиальны. В общем, почти то же самое, что Вы предложили. Будем считать, что оба класса готовы к использованию в программах?
  • 0

#89
yedyge

yedyge
  • Свой человек
  • 879 сообщений
других засад не вижу :D
а как с вашей точки зрения стоит кодировать rectangle::square?
  • 0

#90
Visual1

Visual1
  • В доску свой
  • 1 198 сообщений
Я тоже уверен, что в обоих классах нет никаких нарушений правил проектирования базовых и производных классов. Однако не забываем, что за основу было принято допущение о возможности квадрата быть наследником прямоугольника (то есть, рассматривать его как частный случай прямоугольника, как это принято в математике).

Разработанная модель сама по себе является полной и логически непротиворечивой. Однако она приведет к неприятностям в клиентской программе - как раз к тому времени, когда на разработку иерархии классов будет уже затрачено немало времени. Это можно видеть на примере простой функции:
void g(Rectangle& r)
{
r.SetWidth(5);
r.SetHeight(4);
assert(r.GetWidth() * r.GetHeight()) == 20);
}
Данная функция корректно работает для класса Rectangle. Однако передаваемая в функцию ссылка не обязана всегда указывать на базовый класс. Она может указывать и на производный класс Square - как известно, в этом случае явное приведение типов не требуется. Производный класс обязан уметь вести себя как базовый. Но этого не произойдет - выдача диагностического сообщения и вызов abort для выхода из программы обеспечен!

Вывод: программный (а не геометрический) тип квадрат не может быть наследником типа прямоугольника.

Более подробно об этом можно почитать в статье "The Liskov Substitution Principle". Правда, url статьи мне не известен, так как мне достался готовый файл в формате .pdf. Но думаю, найти его не так уж сложно.
  • 0

#91
Shirson

Shirson
  • Завсегдатай
  • 227 сообщений
Стильно.
  • 0

#92
yedyge

yedyge
  • Свой человек
  • 879 сообщений
не понял. можно ещё раз медленно?
void printtype(Rectangle &r)
{
	printf("\n%s", typeid(r).name());
};

int main(void)
{
	Rectangle *pS = new Square;
	printtype(*pS);

	Square S;
	printtype(S);

	getch();
	return 0;
};

Square
Square


  • 0

#93
yedyge

yedyge
  • Свой человек
  • 879 сообщений
или вы намекаете на то, что второй программер забыл про квадрат как класс, и наваял G(Rectangle &), а третий засунул туда квадрат?
это косяк второго программиста, имхо.

или второй программист всё таки подозревал, что кроме прямоугольника существуют другие фигуры и на всякий случай подстраховался assert-ом?
тогда G() работает совершенно правильно.
это равносильно тому, что второй бы написал assert(typeid(Rectangle) == typeid®) //и это было бы стильнее

Сообщение отредактировал yedyge: 28.08.2006, 12:58:19

  • 0

#94
yedyge

yedyge
  • Свой человек
  • 879 сообщений
Visual1, я понял. второй программист совершенно намеренно и верно записал в G() проверку типа (хотя typeid грамотнее). и ваш вывод о недопустимости square:rectangle не обоснован.

Сообщение отредактировал yedyge: 28.08.2006, 12:59:29

  • 0

#95
Shirson

Shirson
  • Завсегдатай
  • 227 сообщений
(The Liskov Substitution Principle)

void f(Rectangle& r)
{
r.SetWidth(32); // calls Rectangle::SetWidth
}
If we pass a reference to a Square object into this function, the Square object will be corrupted because the height won?t be changed.
  • 0

#96
Visual1

Visual1
  • В доску свой
  • 1 198 сообщений

не понял. можно ещё раз медленно?

void printtype(Rectangle &r)
{
	printf("\n%s", typeid(r).name());
};

int main(void)
{
	Rectangle *pS = new Square;
	printtype(*pS);

	Square S;
	printtype(S);

	getch();
	return 0;
};



Square
Square

Что ж, применение typeid - неплохая идея, но в таком случае:

The typeid operator does a run-time check when applied to an l-value of a polymorphic class type, where the true type of the object cannot be determined by the static information provided. Such cases are:

  • A reference to a class
  • A pointer, dereferenced with *
  • A subscripted pointer (i.e. [ ]). (Note that it is generally not safe to use a subscript with a pointer to a polymorphic type.)
If the expression points to a base class type, yet the object is actually of a type derived from that base class, a type_info reference for the derived class is the result.
© MSDN Library.


Сообщение отредактировал Visual1: 28.08.2006, 15:40:27

  • 0

#97
Visual1

Visual1
  • В доску свой
  • 1 198 сообщений

Visual1, я понял. второй программист совершенно намеренно и верно записал в G() проверку типа (хотя typeid грамотнее). и ваш вывод о недопустимости square:rectangle не обоснован.

Продолжаете ли настаивать на этом своем утверждении?
  • 0

#98
yedyge

yedyge
  • Свой человек
  • 879 сообщений
продолжаю %)

class Rectangle
{
private:
	double Width;
	double Height;
public:
	virtual void SetWidth(double dW) { Width = dW; printf("\nRectangle width"); };
	virtual void SetHeight(double dH) { Height = dH; printf("\nRectangle height"); };
	double GetHeight() const { return Height; };
	double GetWidth() const { return Width; };
};

class Square : public Rectangle
{
public:
	virtual void SetWidth(double dW)
	{
		Rectangle::SetWidth(dW); Rectangle::SetHeight(dW); printf("\nSquare width");
	};
	virtual void SetHeight(double dH)
	{
		Rectangle::SetWidth(dH); Rectangle::SetHeight(dH); printf("\nSquare height");
	};
};

void foo(Rectangle &r)
{
	r.SetWidth(5);
};

int main(void)
{
	Rectangle *pS = new Square;
	Square S;

	pS->SetWidth(10);
	S.SetWidth(10);

	printf("\n\nPassing by reference to foo()");

	foo(*pS);
	foo(S);

	printf("\npS after: %gx%g", pS->GetWidth(), pS->GetHeight());
	printf("\nS after: %gx%g", S.GetWidth(), S.GetHeight());

	getch();
	return 0;
};

Rectangle width
Rectangle height
Square width
Rectangle width
Rectangle height
Square width

Passing by reference to foo()
Rectangle width
Rectangle height
Square width
Rectangle width
Rectangle height
Square width
pS after: 5x5
S after: 5x5

Shirson: не вижу повреждений квадрата данном конкретном в случае (WinNT5, BCB5, VC6). методы вызваны верные, равенство сторон сохраняется.

Visual1: да, именно тот грамотный второй программер, как указано в вашем листинге должен, по-хорошему, убедиться, что имеет в руках именно прямоугольник, если хочет обрабатывать только прямоугольники. мои респекты тому параноику, который пользовал assert. причём неважно как он проверил прямоугольность - через ожидаемую площадь или через type_id.

хотя вы верно намекаете на то, что третий программер может испортить почти любой класс, чтобы коды второго программера заглючили (если второй программер не делает параноидальной проверки типов всех аргументов). очень вероятно, что многие классы не защищены такого саботажа, от std::cin/cout до TDBGrid и std::vector.

но это вопрос скорее культуры и этикета программистов, а не война между враждебными западлистами.

p.s. vc6 предупреждает, что без включения rtti последствия обращения к type_id непресказуемы.
а если включить, то противоположная опция в прекомпилированном заголовнике отменяется.

bcb5 предупреждений не дал, но инсталляция одного левого софта у меня убило msdart.dll из за чего четверть софта перестала работать. то есть я не могу проверить кладётся ли rtti в bcb5.

Сообщение отредактировал yedyge: 28.08.2006, 22:20:08

  • 0

#99
yedyge

yedyge
  • Свой человек
  • 879 сообщений

(The Liskov Substitution Principle)

void f(Rectangle& r)
{
r.SetWidth(32); // calls Rectangle::SetWidth
}
If we pass a reference to a Square object into this function, the Square object will be corrupted because the height won?t be changed.

SetWidth виртуальный?
  • 0

#100
yedyge

yedyge
  • Свой человек
  • 879 сообщений
энтирэсно... http://www.parashift...e.html#faq-21.6

если прямоугольник может что-то невозможное для квадрата, то квадрат нельзя базировать на прямоугольнике

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

перефразируем: "если квадрат может что-то невозможное для прямоугольника, то прямоугольник нельзя базировать на квадрате". типа 21.9

мням... квадрат может автоматически изменять высоту с изменением ширины.

мадам Лискова не упоминается, по ходу. ни разу

вонакак... братья значт типа более далеко идущее отношение

мне показалсь, или вы, Visual1, хотели доказать, что Rectangle:Square лучше, чем Square:Rectangle?
  • 0


Количество пользователей, читающих эту тему: 2

пользователей: 0, неизвестных прохожих: 2, скрытых пользователей: 0

Размещение рекламы на сайте     Предложения о сотрудничестве     Служба поддержки пользователей

© 2011-2022 vse.kz. При любом использовании материалов Форума ссылка на vse.kz обязательна.