Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Общие вопросы по .NET и C# > new keyword в объявление методов


Автор: StepS 1.6.2007, 10:56
Вем привет.

До недавнего времени я был уверен в следующем:
Код

class A{
   public void M1(){
      Console.WriteLine("Class A");
   }
}

class B : A{
    public void M1(){
       Console.WriteLine("Class B");
    }
}


так вот... я был уверен, что если написать так:
Код

  A a = new B();
  a.M1();


на экране появиться строка: "Class A", т.к. в классе B мы не используем ключевое слово new в объявлении метода, который скрывает метод из базового класса,
а если мы напишем new public void M1(){....} в классе В, то на экране появится строка "Class B". Но... как оказалось.. это не так

теперь я понимаю, что ключевое слово new чисто для удобства чтения кода.  или КАК ?
в книге написано: "Без использования ключевого слова new вы рискуете вызвать не тот метод". КАК НА ПРИМЕРЕ ВЫЗВАТЬ НЕ ТОТ МЕТОД ???  smile  у меня не получилось вызвать не тот метод.

Автор: SpaceSpace 1.6.2007, 11:50
Советую все-таки перечитать книгу.
и трех китов: инкапсуляция, полиморфизм, наследование повторить

есть такое дело

ключевое слово NEW - вызывает конструктор класса,
но базовый то у тебя А!!
а, если напишеш
, а потом приведешь
Код

        class A
        {
            public void M1()
            {
                Console.WriteLine("Class A");
            }
        }

        class B : A
        {
            public void M1()
            {
                Console.WriteLine("Class B");
            }
        }
        static void Main(string[] args)
        {
            A g = new B();
           // видиш как хитро :)
            ((B)g).M1();
            Console.Read();
        }

то вызовется нужный метод В!

там все дело в том, что ты создаеш класс А, с его стеком процедур,
а конструктор чужой

а вот если напишешь
Код

        class A
        {
            virtual public void M1()
            {
                Console.WriteLine("Class A");
            }
        }

        class B : A
        {
            override public void M1()
            {
                Console.WriteLine("Class B");
            }
        }
        static void Main(string[] args)
        {
            A g = new B();
            g.M1();
            Console.Read();
        }

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

если в В напишешь
Код

override public void M1(){}

то всегда будет метод В!

Автор: StepS 1.6.2007, 11:56
Спасибо, это я все знаю  smile 
У меня был вопрос про ключевое слово new в объявлении метода.
Как создаются классы я в курсе. Меня интересует имменно ключевое слово new именно в контексте приминения в объявлении метода. С override-ми я тоже знаком и знаю как они работют  smile 

Вопрос про скрытие методов наследуемыми классами.

Автор: archeg 1.6.2007, 12:01
Модификатор new только для удобства чтения кода. С MSDN:
Код

Hiding members without the use of the new modifier is allowed, but generates a warning.

new в C# используется в 3-х случаях:
1) Operator
Код

Class1 o  = new Class1();

Код

Used to create objects and invoke constructors. 

2) Modifier
Код

public class BaseC 
{
    public int x;
    public void Invoke() {}
}
public class DerivedC : BaseC
{
    new public void Invoke() {}
}


Код
When used as a modifier, the new keyword explicitly hides a member inherited from a base class. Hiding an inherited member means that the derived version of the member replaces the base-class version. Hiding members without the use of the new modifier is allowed, but generates a warning. Using new to explicitly hide a member suppresses this warning, and documents the fact that the derived version is intended as a replacement

3) Constraint
Код

class ItemFactory<T> where T : new()
{
    public T GetNewItem()
    {
        return new T();
    }
}

Код

The new constraint specifies that any type argument in a generic class declaration must have a public parameterless constructor. 

Автор: adLucem 1.6.2007, 12:01
new (не полиморфное поведение) в объявлении метода, который скрывает метод базового класса используется только для синтаксического подтверждения понимания того что вы делаете и дополняет слово override (полиморфное поведение).

Автор: StepS 1.6.2007, 12:56
Ок. Я понял, тогда объясните что имелось ввиду под : "может быть вызван не правильный метод" без использования new. Это, кстати из книги, которая обсуждалась на этом форуме: "C# 2005 для проффесионалов".

Автор: adLucem 1.6.2007, 13:02
Если бы new не требовалось то:

Код

public class Base {
    public int Foo ( ) {
        return 1;
    }
}

public class Derived : Base {
    // если бы слово new не указывалось явно, 
    // то программисты могли бы расценивать это как полиморфное замещение
    public int Foo ( ) { // ошибка компилятора
        return 2;    
    }
}


Код

Base obj = new Derived ( );
Console.WriteLine ( obj.Foo ( ) ); // выводится единица

Автор: StepS 1.6.2007, 14:19
ну и что... теперь ставим ключевое слово:
Код

public class Base {
    public int Foo ( ) {
        return 1;
    }
}
public class Derived : Base {
    // если бы слово new не указывалось явно, 
    // то программисты могли бы расценивать это как полиморфное замещение
    public new int Foo ( ) { // ошибка компилятора
        return 2;    
    }
}


Код

Base obj = new Derived ( );
Console.WriteLine ( obj.Foo ( ) ); // ТОЖЕ выводится единица


не пойму, что твой пример показыват ?? кроме как вызов методов идет из типа объекта, а не объекта-типа.

Добавлено через 1 минуту
т.е. как написал archeg это для удобвства использования ?

Автор: ivashkanet 1.6.2007, 15:04
Причем сдесь удобство использования? Это ключевое слово очень важно. 

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

В реализации .Net, если ты определил в наследнике метод с той же самой сигнатурой, что и в базовом но без модификаторов new или override, это равнозначно наличию модификатора new + выводится предупреждение на всякий случай.
В Java, например, все наоборот. Отсутствие модификатора говорит о том, что новый метод переопределяет (override) метод родителя.


Т.е. если ты пришел в .net из Java, то 
Цитата(StepS @  1.6.2007,  09:56 Найти цитируемый пост)
вы рискуете вызвать не тот метод
 что и сказал B]adLucem[/B].

Автор: StepS 1.6.2007, 15:52
ivashkanet можешь привести пример, который без new вызывает из ротительского класса метод (при ссылке на родителя), а с присутствием new вызывает метод из дочернего класса (опять же при ссылке на родителя).
Я проверил на примере - см мой первый пост. Всегда вызывается метод по ссылке на класс.
т.е.

Код

 A a = new B();
 a.M1();


будет всегда отрабатывать метод M1 из класса А, используешь ты new в определении метода (дочернего типа В) или нет !!!!

Цитата

Причем сдесь удобство использования? Это ключевое слово очень важно.

можешь объяснить с примерами как оно важно или дать ссылку где это описано плз?

Автор: stab 1.6.2007, 16:06
Цитата(StepS @  1.6.2007,  19:52 Найти цитируемый пост)
будет всегда отрабатывать метод M1 из класса А, используешь ты new в определении метода (дочернего типа В) или нет !!!!


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

в данном контексте ключевое слово new решает такую проблему:

Код

Derived obj = new Derived ( );
obj.Foo();


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

Автор: adLucem 1.6.2007, 16:19
Цитата(StepS @  1.6.2007,  13:52 Найти цитируемый пост)
который без new вызывает

Без new вы даже код не сможете скомпилировать - это синтаксис языка.
Почему применен именно такой синтаксис - явное подтверждение понимания действия всегда более приоритетно чем поведение по умолчанию (за более авторитетным мнением).

Цитата

For more information, see the following sections in the C# Language Specification:

10.2.2 The new modifier


Что вам еще - MSDN пересказать?


Цитата(StepS @  1.6.2007,  13:52 Найти цитируемый пост)
можешь объяснить с примерами как оно важно или дать ссылку где это описано плз? 


Пример из MSDN:
Цитата

In this example, a nested class hides a class with the same name in the base class. The example demonstrates using the new modifier to eliminate the warning message, as well as accessing the hidden class members by using their fully qualified names.

  Copy Code 
Код

// cs_modifer_new_nested.cs
// Using the new modifier with nested types.
using System;
public class BaseC 
{
    public class NestedC 
    {
        public int x = 200;
        public int y;
    }
}

public class DerivedC : BaseC 
{
    // Nested type hiding the base type members.
    new public class NestedC   
    {
        public int x = 100;
        public int y; 
        public int z;
    }

    static void Main() 
    {
        // Creating an object from the overlapping class:
        NestedC c1  = new NestedC();

        // Creating an object from the hidden class:
        BaseC.NestedC c2 = new BaseC.NestedC();

        Console.WriteLine(c1.x);
        Console.WriteLine(c2.x);   
    }
}



Автор: ivashkanet 1.6.2007, 16:21
Цитата(StepS @  1.6.2007,  14:52 Найти цитируемый пост)
ivashkanet можешь привести пример, который без new вызывает из ротительского класса метод (при ссылке на родителя), а с присутствием new вызывает метод из дочернего класса (опять же при ссылке на родителя)

Нет, конечно, это бред.

Цитата(StepS @  1.6.2007,  14:52 Найти цитируемый пост)
можешь объяснить с примерами как оно важно или дать ссылку где это описано плз? 

Какие примеры? Что ты хочешь понять?

Цитата(StepS @  1.6.2007,  14:52 Найти цитируемый пост)
будет всегда отрабатывать метод M1 из класса А, используешь ты new в определении метода (дочернего типа В) или нет !!!!

ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, 
............................................................................................................................................................................................................................................ 
ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, ДА, 

Так оно и будет. Но дело не в этом.

new означает: "Я, Иванов Иван Иванович, полностью сознаю, что этот метод с такой сигнатурой используется так же в базовом классе, так же я заявляю, что определенный мною метод никоем образом не согласуется с методом базового класса , поэтому при полиморфизме прошу использовать метод базового класса."

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)