public class Base
{
public void DoWork()
{
CoreDoWork();
}
protected virtual void CoreDoWork()
{
Console.WriteLine( "Base.DoWork()" );
}
}
public class Derived : Base
{
protected override void CoreDoWork()
{
Console.WriteLine( "Derived.DoWork()" );
}
}
//Применение шаблона NVIpublic class EntryPoint
{
static void Main()
{
Base b = new Derived();
b.DoWork();
}
}
Чем такая реализация лучше этой?
public class Base
{
public virtual void DoWork()
{
Console.WriteLine( "Base.DoWork()" );
}
}
public class Derived : Base
{
public override void DoWork()
{
Console.WriteLine( "Derived.DoWork()" );
}
}
public class EntryPoint
{
static void Main()
{
Base b = new Derived();
b.DoWork();
}
}
Здравствуйте, Аноним, Вы писали:
bnk>>В вашем случае — ничем. bnk>>А например если вот так, тогда становится понятно:
А>Так это уже тогда Template Method
Тогда извиняюсь... Не очень силен в терминологии...
Я тоже наверное тогда не знаю зачам такое может понадобиться...
Какой смысл делать метод, которрый только и делает что вызывает другой метод?
По-моему это совершенно бессмысленно
Для понимания преимуществ этого паттерна надо перейти на более высокий уровень абстракции. В данном случае мы имеем преимущество сокрытия информации о внутреннем устройстве иерархии Base, Derived.
Я думаю это решение можно применять в областях кода, чреватых частыми изменениями. Для примера, возьмём ситуацию, когда было принято решение отказаться от виртуальности метода DoWork(), или о сворачивании иерархии в один класс. Мне кажется, что первое решение очень сильно облегчит рефакторинг кода.
Мне тоже в свое время хотелось узнать об преимуществах NVI , особенно в свете того что некоторые авторы советуют его применять ВСЕГДА когда есть виртуальная функция.
К сожалению , внятной аргументации я тогда не получил.
Здравствуйте, minorlogic, Вы писали:
M>Мне тоже в свое время хотелось узнать об преимуществах NVI , особенно в свете того что некоторые авторы советуют его применять ВСЕГДА когда есть виртуальная функция.
M>К сожалению , внятной аргументации я тогда не получил.
using System;
namespace Lib
{
public class Base
{
public virtual void Hello()
{
Console.WriteLine("Base::Hello()");
}
}
public class Derived : Base
{
public override void Hello()
{
Console.WriteLine("Derived::Hello()");
}
}
}
// Program.cpp : main project file.#include"stdafx.h"using namespace System;
using namespace Lib;
int main(array<System::String ^> ^args)
{
Derived^ derived = gcnew Derived();
derived->Base::Hello();
return 0;
}
Здравствуйте, Lloyd, Вы писали:
L>Здравствуйте, minorlogic, Вы писали:
M>>Наверное я очень туп но я опять не понял , что вы мне пытались продемонстрировать ? Или ошиблись веткой ?
L>Я пытался продемонстрировать, что пудличные виртуальные функции есть зло, т.к. перекрытую функцию можно "обойти".
С подобной агрументацией я вообще могу сказать что программировать плохо , потому что ошибиться можно. А уж как плохо программировать на C++ если там разрешены статический касты произвольных типов!!!
Здравствуйте, minorlogic, Вы писали:
M>Меня опять это не убедило.
M>Это очень хорошо , точ ее можно обойти.
Как правило, человек, перекрывающий какой-либо метод расчитывает на то, что тот, кто использует экземплр его класса работает через перекрытый метод, а не через базовый метод.
M>Это в дизайне языка и идеалогии программирования на С++.
Здравствуйте, minorlogic, Вы писали:
M>С подобной агрументацией я вообще могу сказать что программировать плохо , потому что ошибиться можно. А уж как плохо программировать на C++ если там разрешены статический касты произвольных типов!!!
Если есть способ избежать ошибки, то по-моему глупо им не воспользоваться.
Здравствуйте, Lloyd, Вы писали:
L>Здравствуйте, minorlogic, Вы писали:
M>>Но вы же явно указали что надо вызвать ? M>>Base::Hello();
L>по твоей логике выходит, что запрещать обращение к приватным членам тоже не нужно — ты же сам явно обратился к приватному члену.
C++ запрещает обращаться к приватным членам. Ты пример написла вообща для какого языка ? я так понял для C# ?
Здравствуйте, minorlogic, Вы писали:
M>>>Но вы же явно указали что надо вызвать ? M>>>Base::Hello();
L>>по твоей логике выходит, что запрещать обращение к приватным членам тоже не нужно — ты же сам явно обратился к приватному члену.
M>C++ запрещает обращаться к приватным членам.
Вах, а зачем? Ты же явно указываешь, что надо вызвать
M>Ты пример написла вообща для какого языка ? я так понял для C# ?
Там смесь из C#-а и плюсов. В C# необходимость использования protected virtual методов еще менее очевидна, т.к. сам C# не позволяет вызвать метод базового класса в обход метода наследника. В то же время .Net этого не запрещает, что я и продемонстрировал на примере C++.
public class Base
{
public void Work()
{
DoWork();
}
protected virtual void DoWork()
{
Console.WriteLine( "Base.Work()" );
}
}
public class Derived : Base
{
public void Job()
{
}
protected override void DoWork()
{
Console.WriteLine( "Derived.Work()" );
}
}
Читатель класса Derived понимает, что DoWork() — специализирует Work(), в то время как Job() — расширяет набор операций базового класса. Иными словами DoWork() определяет специфику поведения операции Work() сохраняя инварианты присущие базовому классу, тогда как Job() — операция не присущая базовому классу, эта операция расширяет набор допустимых действий. Сравниваем с
public class Derived : Base
{
public virtual void Job()
{
Console.WriteLine( "Derived.Job()" );
}
}
Читателю класса не понять: Job() — расширяет или специализирует поведение? Т.е. надо посмотреть а что оно там в Base.
А>//Применение шаблона NVI А>public class EntryPoint А>{ А> static void Main() А> { А> Base b = new Derived(); А> b.DoWork(); А> } А>} А>[/c#]
А>Чем такая реализация лучше этой? А>
А>public class Base
А>{
А> public virtual void DoWork()
А> {
А> Console.WriteLine( "Base.DoWork()" );
А> }
А>}
А>public class Derived : Base
А>{
А> public override void DoWork()
А> {
А> Console.WriteLine( "Derived.DoWork()" );
А> }
А>}
А>public class EntryPoint
А>{
А> static void Main()
А> {
А> Base b = new Derived();
А> b.DoWork();
А> }
А>}
А>
Здравствуйте, afurmanov, Вы писали:
A>Читатель класса Derived понимает, что DoWork() — специализирует Work(), в то время как Job() — расширяет набор операций базового класса. Иными словами DoWork() определяет специфику поведения операции Work() сохраняя инварианты присущие базовому классу, тогда как Job() — операция не присущая базовому классу, эта операция расширяет набор допустимых действий. Сравниваем с
A>
A>public class Derived : Base
A>{
A> public virtual void Job()
A> {
A> Console.WriteLine( "Derived.Job()" );
A> }
A>}
A>
A>Читателю класса не понять: Job() — расширяет или специализирует поведение? Т.е. надо посмотреть а что оно там в Base.