Разница между объектом a = new Dog () и Dog a = new Dog () - PullRequest
27 голосов
/ 19 декабря 2011
object a = new Dog();

против

Dog a = new Dog();

В обоих случаях a.GetType() дает Dog.Оба вызывают один и тот же конструктор (с одинаковой иерархией).

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

Ответы [ 6 ]

36 голосов
/ 19 декабря 2011

Оба создают объект Dog.Только вторая позволяет вам напрямую вызывать методы Dog или иначе обращаться с ним как с собакой, например, если вам нужно передать объект методу как параметр типа Dog (или что-то в иерархии Dog, которая более специфичначем просто object).

object obj = new Dog(); 
// can only see members declared on object
var type = obj.GetType(); // can do this
Console.WriteLine(obj.ToString()); // also this
obj.Bark(); // Error! Bark is not a member of System.Object

Dog dog = new Dog();
// can do all of the methods declared for Object
dog.Bark(); // can finally use the method defined for Dog
6 голосов
/ 19 декабря 2011

new Dog() - это выражение, которое создает новый экземпляр Dog.Он вызывает конструктор без параметров класса Dog.

a - это переменная: ячейка памяти в памяти, которая содержит ссылку на экземпляр Dog после присваивания.

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

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

5 голосов
/ 19 декабря 2011

Оба оператора содержат объявление и вызов конструктора. Вызовы конструктора идентичны, поэтому вы получаете Dog в обоих случаях. Объявления разные: в первом случае вы объявляете переменную типа object, суперкласс Dog; во втором случае вы объявляете переменную типа Dog. Разница в том, что в последующем коде вы можете вызывать методы Dog без преобразования, только когда вы объявите переменную как Dog; если вы объявите его как object, вам понадобится приведение.

5 голосов
/ 19 декабря 2011

Ваша первая строка создает переменную типа object.

Компилятор не позволит вам воспринимать это как Dog.

4 голосов
/ 19 декабря 2011

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

Однако операторы также имеют другую часть: объявление переменной (это часть оператора до равенства).В статически типизированных языках, таких как C #, каждая переменная - в общем, любое выражение - имеет статический тип:

object a = new Dog(); // static type: object / runtime type: Dog
Dog b = new Dog();    // static type: Dog / runtime type: Dog

Компилятор не позволит вам присвоить значение переменной, которую он не может Докажи, что имеет статический тип переменной, например, он не позволяет

Cat c = new Dog(); // unless Dog derives from Cat, which we know isn't true

, поскольку все ссылочные типы неявно происходят от System.Object,присвоение Dog переменной статического типа object в порядке. Вы можете думать о «статическом типе» как о том, что объект «объявлен как». Вы всегда можете определить статический тип чего-то , просто прочитав исходный код ;это то, как это делает компилятор.

Тогда есть также тип времени выполнения каждой переменной (выражения), о котором я упоминал выше.Это одинаково в обоих случаях, потому что, в конце концов, в обоих случаях мы создали Dog. Вы можете думать о «типе времени выполнения» как о том, чем на самом деле является объект . Тип времени выполнения чего-либо не может быть определен просто путем чтения источника;Вы определяете его только во время работы программы, отсюда и название.В C # это делается путем вызова GetType.

Должно быть очевидно, что тип времени выполнения - это то, без чего вы не можете обойтись¹; все в конце концов должно быть чем-то.Но зачем изобретать понятие статического типа?

Вы можете думать о статических типах как о договоре между вами (программистом) и компилятором.Объявляя статический тип b равным Dog, вы сообщаете компилятору, что не собираетесь использовать эту переменную для хранения чего-либо, кроме Dog.Компилятор, в свою очередь, обещает не позволить вам нарушить вашу заявленную цель и выдает ошибку, если вы пытаетесь это сделать.Он также не позволяет вам использовать d любым способом, который не должен поддерживаться каждым типом Dog.

Обратите внимание:

class Dog {
    public void Woof();
}

Dog d = new Dog();
d.Woof(); // OK

object o = new Dog();
o.Woof(); // COMPILER ERROR

Последняя строка вызываетошибка компилятора, потому что она нарушает контракт статической типизации: вы сказали компилятору, что o может быть чем угодно, происходящим от System.Object, но не все вещи, происходящие от этого, имеют метод Woof.Таким образом, компилятор пытается защитить вас, говоря: «Что вы там делаете? Я не могу доказать… что все, что в o может говорить! Что, если бы это было Cat?».

Примечания:

¹ Это не значит, что каждый объект волшебным образом знает, что он «есть» на всех языках.В некоторых случаях (например, в C ++) эта информация может использоваться при создании объекта, но затем «забывается», чтобы дать компилятору больше свободы для оптимизации кода.Если это происходит, объект все еще является чем-то, но вы не можете ткнуть его и спросить его «кто вы?».

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

2 голосов
/ 06 января 2012

Это полезно, когда вы хотите использовать полиморфизм, и вы можете использовать абстрактный метод, который имеет реализацию в Dog.Следовательно, таким образом, объект - это Собака, а также Объект.Таким образом, вы можете использовать этот способ, если хотите использовать полиморфизм.

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