Неужели на C# такое не сделать???
От: IvanM Россия  
Дата: 09.12.03 06:05
Оценка:
Всем привет.

На С++ это выглядит вот так:

class Control
{
protected:
    virtual void SomeMethod()
    {
        //Делает то, что нужно
    }
};

class SomeStandatdControl : public Control
{
protected:
    virtual void SomeMethod()
    {
        //Делает не то, что нужно
    }
};

class MyControl : public SomeStandatdControl
{
protected:
    virtual void SomeMethod()
    {
        //Вот тут вызов нужного метода через явную квалификацию
        Control::SomeMethod();
    }
};

А теперь вопрос, как такое написать на шарпе?

public class Control
{
    protected virtual void SomeMethod()
    {
        //Делает то, что нужно
    }
}

public class SomeStandatdControl : Control
{
    protected override void SomeMethod()
    {
        //Делает не то, что нужно
    }
}

public class MyControl : SomeStandatdControl
{
    protected override void SomeMethod()
    {
        //Как тут вызвать Control.SomeMethod???
        Control.SomeMethod(); // Error: Cannot access protected member 
        (this as Control).SomeMethod(); // Error: Cannot access protected member 
    }
}
Re: Неужели на C# такое не сделать???
От: Алексей Одинцов Россия  
Дата: 09.12.03 06:57
Оценка:
public class Control
{
    protected virtual void SomeMethod()
    {
        SomeMethodOfControl();
    }

    protected void SomeMethodOfControl()
    {
        //Делает то, что нужно
    }
}

public class SomeStandatdControl : Control
{
    protected override void SomeMethod()
    {
        //Делает не то, что нужно
    }
}

public class MyControl : SomeStandatdControl
{
    protected override void SomeMethod()
    {
        //Как тут вызвать Control.SomeMethod???
        //Control.SomeMethod(); // Error: Cannot access protected member 
        //(this as Control).SomeMethod(); // Error: Cannot access protected member 
        SomeMethodOfControl();
    }
}


иначе никак.
для вызова предыдущего в цепочке: base.SomeMethod();
Re: Неужели на C# такое не сделать???
От: Воронков Василий Россия  
Дата: 09.12.03 07:35
Оценка: +1 -1
Надо пока не поздно написать в МС, может, в следующей версии добавят. :crush: Хотя ты первый, кому это понадобилось.

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

Уроды, в общем.
Posted via RSDN NNTP Server 1.8 beta
Re[2]: Неужели на C# такое не сделать???
От: Dr_Sh0ck Беларусь  
Дата: 09.12.03 07:38
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Уроды, в общем.


Согласен. Кто мешал сделать что-либо наподобие:
base(className).classMember

Do not fake yourself ;)
ICQ#: 198114726
Re[3]: Неужели на C# такое не сделать???
От: Алексей Одинцов Россия  
Дата: 09.12.03 07:49
Оценка: 7 (1) +1
Здравствуйте, Dr_Sh0ck, Вы писали:

Это вопрос-то скорее философский. Если разработчик базового класса сделал свою реализацию — зачем вам лезть дальше в дебри дерева наследования, чтобы вытащить что-то оттуда из самого нутре? Мало ли зачем он его перегрузил — может он там состояние объекта своего меняет? А вы хотите в обход его реализации пойти.

А если Вы сами разрабочик обоих классов — легко сделаете то что например я предлагал, если уж не хочется повторять реализацию.

D_S>Здравствуйте, Воронков Василий, Вы писали:


ВВ>>Уроды, в общем.


D_S>Согласен. Кто мешал сделать что-либо наподобие:

D_S>
D_S>base(className).classMember
D_S>

D_S>
Re[4]: Неужели на C# такое не сделать???
От: Dr_Sh0ck Беларусь  
Дата: 09.12.03 07:56
Оценка: :)
Здравствуйте, Алексей Одинцов, Вы писали:

АО>Здравствуйте, Dr_Sh0ck, Вы писали:


АО>Это вопрос-то скорее философский.


Да фишка еще и в том, что философия склонна меняться. Особенно у известной всем конторы...
Do not fake yourself ;)
ICQ#: 198114726
Re[4]: Неужели на C# такое не сделать???
От: IvanM Россия  
Дата: 09.12.03 08:21
Оценка:
Здравствуйте, Алексей Одинцов, Вы писали:

АО>Здравствуйте, Dr_Sh0ck, Вы писали:


АО>Это вопрос-то скорее философский. Если разработчик базового класса сделал свою реализацию — зачем вам лезть дальше в дебри дерева наследования, чтобы вытащить что-то оттуда из самого нутре? Мало ли зачем он его перегрузил — может он там состояние объекта своего меняет? А вы хотите в обход его реализации пойти.


Вот именно меняет. Только одна маленькая деталь, не своего объекта, а уже нашего общего. Могу же я у собственного объекта сам выбирать поведение. И это поведение уже на 80% реализовано в пред-базовом, а потом в базовом урезано. Да дело даже не в этом. В данной ситуации я не могу вызвать защищенный метод своего предка. Доступ к защищенным методам предка это мое законное право как наследника, а тут меня его лишают. Какого хрена? В чем тут логика или хотябы философия???
Re[5]: Неужели на C# такое не сделать???
От: Алексей Одинцов Россия  
Дата: 09.12.03 08:26
Оценка: 2 (2) +1
Здравствуйте, IvanM, Вы писали:

IM>Здравствуйте, Алексей Одинцов, Вы писали:


АО>>Здравствуйте, Dr_Sh0ck, Вы писали:


АО>>Это вопрос-то скорее философский. Если разработчик базового класса сделал свою реализацию — зачем вам лезть дальше в дебри дерева наследования, чтобы вытащить что-то оттуда из самого нутре? Мало ли зачем он его перегрузил — может он там состояние объекта своего меняет? А вы хотите в обход его реализации пойти.


IM>Вот именно меняет. Только одна маленькая деталь, не своего объекта, а уже нашего общего. Могу же я у собственного объекта сам выбирать поведение. И это поведение уже на 80% реализовано в пред-базовом, а потом в базовом урезано. Да дело даже не в этом. В данной ситуации я не могу вызвать защищенный метод своего предка. Доступ к защищенным методам предка это мое законное право как наследника, а тут меня его лишают. Какого хрена? В чем тут логика или хотябы философия???


в том же, почему и некоторые члены вашего предка вам недоступны (are private). Разработчик вашего базового класса сделал свою реализацию, деталей которой вы не знаете. Если позволить вам исключить из работы его функциональность — его (и ваш) класс станет вести себя неправильно. Если вам очень хочется вызвать Control.SomeMethod() — унаследуйтесь напрямую от него и повторите реализацию так как вам нравится, либо уж используйте базовый класс таким какой он есть.

Если же вы сами разработчик всех трех классов — значит учитесь правильнее проектировать иерархии классов.
Re[6]: Неужели на C# такое не сделать???
От: IvanM Россия  
Дата: 09.12.03 09:30
Оценка: -1
Здравствуйте, Алексей Одинцов, Вы писали:

АО>Здравствуйте, IvanM, Вы писали:


IM>>Здравствуйте, Алексей Одинцов, Вы писали:


АО>в том же, почему и некоторые члены вашего предка вам недоступны (are private). Разработчик вашего базового класса сделал свою реализацию, деталей которой вы не знаете. Если позволить вам исключить из работы его функциональность — его (и ваш) класс станет вести себя неправильно. Если вам очень хочется вызвать Control.SomeMethod() — унаследуйтесь напрямую от него и повторите реализацию так как вам нравится, либо уж используйте базовый класс таким какой он есть.


АО>Если же вы сами разработчик всех трех классов — значит учитесь правильнее проектировать иерархии классов.


Я не говорю здесь про private, это совершенно другое, о них не пишут в документации, их вобще нет. Раз уж дело дошло до обсуждения вопросов проектирования, то мое мнение — любое дублирование кода (кода предка в наследнике в частности) ведет к проблемам при последующей поддержке в целостном состоянии. И тут любая разумная возможность повторного использования кода — благо. В данном случае, IMHO, ситуация разумная. По поводу иерархии
1. Не всегда мы можем все спроектировать сами, иногда это уже сделали за нас.
2. Идеальные иерархии в реальной жизни попадаются не всегда.

А что касается "вести себя неправильно", откуда такая уверенность, что непременно все начнет вети себя неправильно? Точно так же можно запретить доступ к защищеннвм полям класса. А вдруг мы их изменим и все начнет вести себя неправильно? Это паранойя а не логика.
Re[7]: Неужели на C# такое не сделать???
От: Алексей Одинцов Россия  
Дата: 09.12.03 13:15
Оценка:
реализация функции — её код — такая же private как и приватные члены класса. то, что вам доступно вызвать её не говорит о том, что вы можете делать предположения о её коде.

если вы сами проектируете иерархии — у вас есть выход.

если не сами — Вам придется следовать логике программиста создавшего для Вас базовый класс. Вам не нравится его логика — напишите свой класс со своей. Если это невозможно по каким-то причинам (например, вы вынуждены использовать его как базовый) — увы. придется выкручиваться.

Но логика в таком подходе есть. Не сказал бы что я её разделяю, но мне всего пару раз пришлось столкнуться с этим ограничичением, и не могу сказать что оно такое уж драконовское. В C# и шаблонов пока нет, ну и что теперь? Хотите писать как на C++ — пишите на C++. Или пишите в MS пусть сделают эту Вашу фичу. Я ей применение тоже найду, хоть пока и не считаю её такой уж нужной.
Re[8]: Неужели на C# такое не сделать???
От: IvanM Россия  
Дата: 09.12.03 14:14
Оценка:
Здравствуйте, Алексей Одинцов, Вы писали:

АО>Но логика в таком подходе есть. Не сказал бы что я её разделяю, но мне всего пару раз пришлось столкнуться с этим ограничичением, и не могу сказать что оно такое уж драконовское. В C# и шаблонов пока нет, ну и что теперь? Хотите писать как на C++ — пишите на C++. Или пишите в MS пусть сделают эту Вашу фичу. Я ей применение тоже найду, хоть пока и не считаю её такой уж нужной.


Вобщем, понятна логика. Во первых, С++ это не C#, а во вторых, ООП это не то, что я о нем думаю. Но, в любом случае, спасибо за ответ!
Re[5]: Неужели на C# такое не сделать???
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 10.12.03 12:49
Оценка:
Здравствуйте, IvanM, Вы писали:

IM>Вот именно меняет. Только одна маленькая деталь, не своего объекта, а уже нашего общего. Могу же я у собственного объекта сам выбирать поведение. И это поведение уже на 80% реализовано в пред-базовом, а потом в базовом урезано. Да дело даже не в этом. В данной ситуации я не могу вызвать защищенный метод своего предка. Доступ к защищенным методам предка это мое законное право как наследника, а тут меня его лишают. Какого хрена? В чем тут логика или хотябы философия???


public class A
{
    private ArrayList _list;
    
    public A()
    {
        Init();
    }
    
    protected virtual void Init()
    {
        _list = new ArrayList();
    }
    
    public virtual void Add(object item)
    {
        _list.Add(item);
    }
}

public class B : A
{
    private ArrayList _list2;
    
    protected override void Init()
    {
        base.Init();
        _list2 = new ArrayList();
    }
    
    public override void Add(object item)
    {
        base.Add(item);
        _list2.Add(item);
    }
}

public class C
{
    protected override void Init()
    {
        ((B)this).Init();
    }
}

...

C c = new C();
c.Add(25); // Null reference exception
... << RSDN@Home 1.1.2 beta 2 >>
AVK Blog
Re[6]: Неужели на C# такое не сделать???
От: Алексей Одинцов Россия  
Дата: 10.12.03 12:57
Оценка:
Здравствуйте, AndrewVK, Вы писали:

а к чему этот код?

у тому же он не компилится в 1.1
даже после добавления : B к объявлению класса C.

в чем Вы его компилиировали?
Re[7]: Неужели на C# такое не сделать???
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 10.12.03 13:11
Оценка:
Здравствуйте, Алексей Одинцов, Вы писали:

АО>а к чему этот код?


чем тут логика или хотябы философия???


АО>у тому же он не компилится в 1.1

АО>даже после добавления : B к объявлению класса C.

АО>в чем Вы его компилиировали?


Ни в чем. Понятно что вызов через голову невозможен. Это демонстрация проблем если бы такая возможность была.
... << RSDN@Home 1.1.2 beta 2 >>
AVK Blog
Re[8]: Неужели на C# такое не сделать???
От: Алексей Одинцов Россия  
Дата: 10.12.03 13:22
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Ни в чем. Понятно что вызов через голову невозможен. Это демонстрация проблем если бы такая возможность была.


тогда надо ((A)this).Init(); т.к. ((B)this).Init(); это то же что и base.Init();

а то несколько непонятно что пытались продемонстрировать.
Re[9]: Неужели на C# такое не сделать???
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 10.12.03 13:51
Оценка:
Здравствуйте, Алексей Одинцов, Вы писали:

АО>тогда надо ((A)this).Init(); т.к. ((B)this).Init(); это то же что и base.Init();


Ну да
... << RSDN@Home 1.1.2 beta 2 >>
AVK Blog
Re: Неужели на C# такое не сделать???
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 10.12.03 15:29
Оценка:
Здравствуйте, IvanM, Вы писали:

Попробуй через делегаты. В Delphi обычная практика через TMethod.
Через рефлектор или CreateDelegate найти адрес метода и вствить его в соответствующее поля делегата, а на место ссылки на объект this.
и солнце б утром не вставало, когда бы не было меня
Re[6]: Неужели на C# такое не сделать???
От: IvanM Россия  
Дата: 10.12.03 17:07
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Здравствуйте, IvanM, Вы писали:


AVK>...


Да я уже все понял, просто С++ ная привычка, что все можно
Re[2]: Неужели на C# такое не сделать???
От: Dax  
Дата: 11.12.03 12:07
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>Через рефлектор или CreateDelegate найти адрес метода и вствить его в соответствующее поля делегата, а на место ссылки на объект this.


Не выйдет.
Делегат — не адрес метода, он намертво с объектом-владельцем метода связан. А как раз-таки ссылку на "объект-дедушку" вычислить не получится. Боюсь, что в VTBL текущего обекта даже упоминания нет про "дедушкин" метод. Такое пройдет только со статическим методом или если "дед" сам такой делегат вернет.
Re[3]: Неужели на C# такое не сделать???
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 11.12.03 12:21
Оценка:
Здравствуйте, Dax, Вы писали:

Dax>Делегат — не адрес метода, он намертво с объектом-владельцем метода связан. А как раз-таки ссылку на "объект-дедушку" вычислить не получится. Боюсь, что в VTBL текущего обекта даже упоминания нет про "дедушкин" метод. Такое пройдет только со статическим методом или если "дед" сам такой делегат вернет.

Почему же, делегат как раз имеет списочную структуру типа TMethod. А вот как выдернуть ссылку на дедушкин метод это другая проблема. Если это не абстрактный класс или через неабстрактного наследника не перекрывающего этот метод адрес выдернуть метода выдернуть можно просто создав объект этого типа создать делегат с его методом и заменить ссылку на объект на this.
и солнце б утром не вставало, когда бы не было меня
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.