オブジェクトa = new Dog()とDog a = new Dog()の違い

object a = new Dog();

Dog a = new Dog();

どちらの場合も、 a.GetType() Dog です。 どちらも同じコンストラクター(同じ階層)を呼び出します。

それでは、これら2つのステートメントの違いを教えてください。

27
あなたは "意味の違いは何ですか?" 「どちらを使うべきなの?
追加された 著者 Jay Bazuzi,
@slugster - shhhh 担当者が養子になるまで待ちます。
追加された 著者 Paul Bellora,
@ケンなぜインターフェイスを使用しないのですか? Like HousePet a =新しい犬();.共有メソッドをHousePetインターフェースまたはAnimalインターフェースに置く。
追加された 著者 Andy,
このHASは重複している...
追加された 著者 slugster,
私が見つけた美しさは、メソッドが Dog 以上のもので動作する必要があることがあります。 Object a = new Dog()ステートメントを使用すると、メソッドで使用できます。同様に、 Object b = new Cat()を実行することができます。同様に使用できます。
追加された 著者 user569322,

6 答え

どちらもDogオブジェクトを作成します。 2番目のメソッドだけでは、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
36
追加された
@Omkarpanhalkarは、変数ではなく、インスタンスの型を取得しています。これは、インスタンスに関連付けられたメタデータを取得する実行時メカニズムであり、実行時にインスタンスがDogであることがわかります。あなたが失ったのは、コンパイル時のメリットです。
追加された 著者 Anthony Pegram,
次回は似たような質問をしましたが、英語の母国語以外の母国語として "xxxのように扱う"を使用します。
追加された 著者 Danny Chen,
@Omkarpanhalkar:この答えは、表現する能力が本当に重要であり、全体的な品質の一部であることに気付きました。私は同様の質問(英語だけでなく母語でも)に答えていましたが、私はいつも悪い表現をしています。
追加された 著者 Danny Chen,
@ダニーチェンなぜそれはそうですか?
追加された 著者 om471987,
@AnthonyPegramありがとうございました。知らなかったよ。
追加された 著者 om471987,
ありがとう。私はあなたに同意します。しかし、私は次のコードオブジェクトを書くとき=新しいDog(); Console.WriteLine(a.GetType());私は犬としてではなく、オブジェクトである。それはなぜですか?
追加された 著者 om471987,

new Dog() is an expression that creates a new Dog instance. It invokes the parameterless constructor of the Dog class.

a is a variable: a storage cell in memory that holds a reference to the Dog instance after assignment.

違いは、 Dog 変数は Dog インスタンス(または Dog から派生するクラスのインスタンス) object 変数は object インスタンス(または object から派生したクラスのインスタンスDog クラスでも同様です)。

Dog 変数がある場合、参照されるインスタンスで Dog クラス(およびその基本クラス)によって定義されたメソッドを呼び出すことができます。 object 変数がある場合、そのインスタンスの object クラスのメソッドのみを呼び出すことができます。

6
追加された
a で参照される Dog インスタンスでGetTypeメソッドを呼び出すためです。 GetTypeは、変数ではなくインスタンスの型を返します。
追加された 著者 dtb,
ありがとう。私はあなたに同意します。しかし、私は次のコードオブジェクトを書くとき=新しいDog(); Console.WriteLine(a.GetType());私は犬としてではなく、オブジェクトである。それはなぜですか?
追加された 著者 om471987,

両方のステートメントには、宣言とコンストラクター呼び出しが含まれています。コンストラクタの呼び出しは同一であるため、どちらの場合でも Dog を取得します。宣言は異なります。最初のケースでは、 Dog のスーパークラスである object 型の変数を宣言します。 2番目のケースでは、 Dog 型の変数を宣言します。違いは、次のコードでは、変数を Dog として宣言したときにのみ、キャストなしで Dog のメソッドを呼び出すことができます。 object として宣言すると、キャストが必要になります。

5
追加された

最初の行は、 object 型の変数を作成します。

コンパイラはそれを Dog として扱うことはできません。

5
追加された
あなたがそれをキャストしない限り。 (Dog)a
追加された 著者 Peter Olson,
@PeterOlsonこの場合は、もはやプレーンなオブジェクトではありません...
追加された 著者 poke,

両方のステートメントには、あなたが言及したように 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

すべての 参照型 は、静的型 object の変数に Dog を代入すると、 System.Object 「静的型」は、オブジェクトが「宣言されたもの」と考えることができます。静的型は、ソースコードを読むだけでいつでも判断できます。これはコンパイラがこれを行う方法です。

次に、上で述べた各変数(式)のランタイムタイプもあります。いずれの場合も、 Dog が作成されているため、どちらの場合も同じです。 オブジェクトは実際に存在しているものとして "ランタイムタイプ"と考えることができます。ランタイムタイプは、ソースを読み込むだけでは判別できません。あなたがプログラムを実行している間だけそれを決定するので、その名前になります。 C#では、これは GetType を呼び出すことによって行われます。

ランタイムタイプは、あなたが¹なしではできないものであることは明らかです。結局のところ、すべては何か「ある」必要があります。しかし、なぜ静的なタイプの概念を発明するのに気をつけますか?

あなた(プログラマー)とコンパイラの間の契約として、静的型を考えることができます。静的型 b Dog に宣言することにより、その変数を Dog コード>。コンパイラは、あなたの宣言された目的に違反させないように約束します。また、あらゆる種類の Dog がサポートしないような方法で d を使用できないようにします。

検討してください:

class Dog {
    public void Woof();
}

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

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

最後の行は、静的型付け契約に違反するため、コンパイラエラーが発生します。コンパイラに、 o System.Object そこから派生するのは Woof メソッドです。コンパイラは "あなたは何をしていますか?" Cat の場合はどうでしょうか? 。

メモ:

¹これは、すべてのオブジェクトがすべての言語で「ある」ことを魔法のように知っていることを意味するものではありません。場合によっては(例えばC ++の場合)、この情報はオブジェクトの作成時に使用されるかもしれないが、コンパイラがコードを最適化する自由をより自由に取れるようにするために "忘れてしまう"。これが起こった場合、オブジェクトはまだ何かありますが、あなたはそれを突き刺して "あなたは何ですか?"と尋ねることはできません。

²実際に、この簡単な例では、それを証明することができます。しかし、静的な型のコントラクトを尊重することがポイントなので、この知識を使用することを選択しません。

4
追加された
@DanielPryden:実行時の型に関しては、オブジェクトがまだ何か何かであることが明らかになるようにその文章を改めました。(例えば、何が正確かを決めるvtableを持っているかもしれませんが)情報を取り戻す多型に関して、あなたの意見は完全に正しいです。それは私がAFKだった最後の数時間のために削除したいと思っていた、私の部分では単に悪い最後の分の思考だった。
追加された 著者 Jon,
いい答えだ!これは良い説明です。私はちょうどいくつかの小説をいくつか持っています。最初に、「実行時の型は、実行不可能な型ではないことは明らかです。」 - そして、ランタイム型の追跡をサポートしていない静的型付き言語があります。 (例えば、実行時の型情報であるRTTIはC ++ではオプションです。)これを動作させるためには、プログラマのキャストの使用を盲目的に信頼する必要があります:このオブジェクトが実際にDogだと言うと、実行時のDog、またはVery Bad Things(未定義の動作)が発生します。しかし、それは動作します。
追加された 著者 Daniel Pryden,
第2に、 GetType()が実行時の型を返すと説明したときに、仮想メソッドのディスパッチについて簡単に説明すると役に立ちます。 (私の頭の上からは、実際に GetType()が仮想呼び出しであるかどうかはわかりませんが、概念を説明するのに便利です)。静的型ではなくランタイム型に基づいてメソッド呼び出しをディスパッチできるため、仮想メソッドが原因です。実際には、静的型を持たない多態性を持つことができます。PythonやRubyを見てください。
追加された 著者 Daniel Pryden,

これは、多態性を使用したい場合に便利で、Dogに実装されている抽象メソッドを使用できます。したがって、このようにオブジェクトはDogであり、オブジェクトもそうです。したがって、多態性を使用する場合は、この方法を使用できます。

2
追加された