class Dog
{
}
class BullDog : Dog
{
}
class Program
{
static void Main()
{
Dog dog2 = new BullDog();
BullDog dog3 = new BullDog();
}
}
使用Dog作为参考与BullDog作为参考有什么区别?
我习惯使用var dog3 = new BullDog();
,类似于BullDog dog2 = new BullDog();
。我们什么时候需要使用Dog dog2 = new BullDog();
?
答案 0 :(得分:4)
编辑:要解决评论中的其他问题:
static void TakesDog(Dog theDog) { ... }
static void TakesBulldog(Bulldog theBulldog) { ... }
static void TakesObject(object theObject) { ... }
static void Main()
{
//Given these declarations...
object dog = new BullDog();
Dog dog2 = new BullDog();
BullDog dog3 = new BullDog();
//These calls will work because a BullDog is a Dog:
TakesDog(dog2);
TakesDog(dog3);
//this call will work because a Bulldog is a Bulldog:
TakesBulldog(dog3);
//and these calls will ALL work because all Dogs are Objects:
TakesObject(dog);
TakesObject(dog2);
TakesObject(dog3);
//However, these calls will fail because an Object or Dog is not
//necessarily a Bulldog,
//EVEN THOUGH our current dog and dog2 are indeed references to Bulldogs:
TakesBulldog(dog);
TakesBulldog(dog2);
//An explicit conversion is necessary to make the above calls work:
TakesBulldog(dog2 as Bulldog); //works given the current reference
TakesBulldog((Bulldog)dog2); //works given the current reference
TakesBulldog(dog as Bulldog); //ditto
TakesBulldog((Bulldog)dog); //ditto
//but if we change the value of dog2 to some other dog:
dog2 = new Labrador();
//the above calls now fail:
TakesBulldog(dog2 as Bulldog); //passes null into the method
TakesBulldog((Bulldog)dog2); //throws InvalidCastException
//you can avoid problems by checking the true type:
if(dog2 is Bulldog) //interrogates the type of the referenced object
TakesBulldog((Bulldog)dog2); //works
else
TakesDog(dog2); //general fallback case
//Object is similar but even more basic:
dog = "I'm a dog"; //now dog is a System.String
//this call still works:
TakesObject(dog);
//but these will fail:
TakesDog(dog);
TakesBulldog(dog);
}
最后要明白的一点是:
//given these declarations:
object dog = new BullDog();
BullDog dog2 = new BullDog();
//even though dog is a BullDog, attempting to call BullDog-specific
//members (methods, properties, fields) will fail:
dog.Drool();
//you may only call members as specific as the object type of the
//variable holding the reference:
dog.ToString(); //defined by Object. If you've overridden it in Dog or BullDog,
//you'll get that implementation
dog2.Drool(); //works because we know from the variable that dog2 is a BullDog.
答案 1 :(得分:3)
使用基类型作为引用类型时,只能调用在基类型上定义的成员。你需要强制转换才能使用超类型的成员。
因此,如果BullDog
定义了DoNotRelease
方法,则无法直接从Dog
引用中调用它。
就var
而言,它会推断出更具体的类型。因此,如果使用new BullDog()
,推断类型将为BullDog
。
答案 2 :(得分:3)
通常在使用继承时,您还将使用重载。
但请考虑以下因素:
static void Main()
{
Dog dog = new BullDog();
BullDog bulldog = new BullDog();
dog.Execute();
bulldog.Execute();
}
class Dog
{
public virtual void Execute()
{
Console.WriteLine("Execute Dog");
}
}
class BullDog : Dog
{
public new void Execute() // use new instead of override
{
Console.WriteLine("Execute BullDog");
}
}
这将打印:
Execute Dog
Execute BullDog
如果要访问仅适用于该类型的函数,则需要定义子类型。如果你想使用运算符重载的方式(使用覆盖运算符),你可以使用这个子类行为,而不必担心当前的类型。
<强> - 编辑 - 强>
您要求区别:
object a3 = new BullDog();
BullDog a3 = new BullDog();
嗯,对于初学者来说,在相同的范围内,这会给你一个编译错误,因为a3不能被定义两次。但是,让我们说你在不同的范围内定义它们。
在对象a3上,您只能调用可在对象上使用的方法(Equals,GetHashCode,ToString,GetType())。如果你想在它上面使用只能在Dog类中使用的方法,你必须把它投射到Dog。
object a3 = new BullDog();
BullDog a4 = new BullDog();
if (a3 is Dog)
{
// only executes when a3 is a Dog
// a3 is for the compiler still of type object, so you can't call any other methods on it
}
Dog d1 = a3 as Dog; // cast it to a dog
if (d1 != null) // if d1 == null, then a3 was not of type dog and the cast returned null
{
d1.Execute(); // we know now that d1 is a dog and that it points to a dog instance so we can call a dog method on it.
}
a4.Execute();
答案 3 :(得分:1)
您不需要Dog dog2 = new BullDog()
,您可以将BullDog
传递给期望Dog
的任何方法。
查看http://en.wikipedia.org/wiki/Polymorphism_in_object-oriented_programming
答案 4 :(得分:1)
让我们定义另一个类:
class OtherDog : Dog
{
}
现在您可以定义如下列表:
C#:
List<Dog> Dogs = new List<Dog>();
Dogs.Add(new BullDog());
Dogs.Add(new OtherDog());
你有一个Dog类型的列表,但可以添加BullDog和OtherDog类型
这是OOP主题之一,名称为“Polymorphism”
ex2:
让我们想你想要开发一个颜料:
class Shape ()
{
virtual public void Draw()
{
}
}
class Rectangle : Shape ()
{
override public void Draw()
{
}
}
class Circle : Shape ()
{
override public void Draw()
{
}
}
void main ()
{
List<Shape> Shapes = new List<Shape>();
Shapes.Add(new Rectangle());
Shapes.Add(new Circle());
Shape[1].Draw(); //Draw a rectangle
Shape[2].Draw(); // Draw a circle
}
如果您需要更多详细信息,请评论我编辑我的回复以获取更多详细信息
thansk,阿里
答案 5 :(得分:1)
问:“使用Dog作为参考与BullDog作为参考有什么区别?”
答:如果您有Dog引用,则您添加到派生类型BullDog的任何其他方法/属性/字段将无法公开访问。
E.g。如果你有:
public class Dog
{
public virtual void Bark()
{
Console.WriteLine("Woof");
}
}
public class BullDog : Dog
{
public override void Bark()
{
Console.WriteLine("BOWF!");
}
public void Slobber()
{
Console.WriteLine("I cannot control my drool :(");
}
{
......你将无法做到这一点:
Dog baseDog = new BullDog();
baseDog.Slobber(); // error -- Dog doesn't know how to slobber.
...因为基本类型不存在该方法。
此外,根据您是否有基本/派生引用,如果您不小心使用new运算符,也会出现一些微妙的问题。然而,根据我的经验,这些事件非常罕见(参见Wouter de Kort的帖子,因为他刚刚在我输入时发布了更好的解释)。
问:“我习惯使用var dog3 = new BullDog();这类似于BullDog dog2 = new BullDog();我们什么时候需要使用Dog dog2 = new BullDog();?”答:你甚至可能不知道你得到了什么类型的Dog
,你所知道的是......它是Dog
。考虑......
public static class DogFactory
{
public static Dog CreateMysteryDog()
{
return new Shitzu();
}
}
Dog dog = DogFactory.CreateMysteryDog(); // what is the concrete type of Dog?
DogFactory返回Dog
引用,而不是Shitzu
引用,因此您必须使用基类型。在这种情况下,var也将是Dog
而不是Shitzu
。