我是面向对象和编程的新领域。还有一些我仍在努力理解的事情。
例如,我有以下代码:
public abstract class ParentA
{
public virtual void MethodA()
{
Console.WriteLine("Doing somethin...");
}
}
public class DerivedClassA : ParentA
{
public override void MethodA()
{
Console.WriteLine("Doing something from derived...");
}
}
现在,我看到了一些代码实例化的代码:
ParentA p = new DerivedClassA();
p.MethodA();
为什么不只是实例化你想要使用的实际课程并使用它的成员?
DerivedClassA d = new DerivedClassA();
d.MethodA();
我看到这里使用了很多接口,其中的内容如下:
public interface Animal
{
void Bark();
}
public class Dog : Animal
{
public void Bark()
{
Console.WriteLine("bark");
}
}
然后以这种方式使用:
Animal a = new Dog();
a.Bark();
为什么不这样做?:
Dog d = new Dog();
d.Bark();
什么时候重要?
感谢您的帮助
:)
答案 0 :(得分:12)
你是对的;看起来很奇怪,不是吗?
代码:
Animal animal = new Dog();
相当罕见;通常,如果你知道你正在制作一只狗,那么你可以输入变量为Dog。更常见的是:
Animal animal = petStore.ObtainInexpensivePet();
你不确切知道会回来的是什么;也许是一只小猫,也许是一只鬣蜥,但你知道它至少会成为一只动物。这是创建狗对象的宠物商店,而不是你。
答案 1 :(得分:5)
此技术可用于确保代码未与特定实现耦合。
如果此特定派生类具有其他方法(例如,List<T>
),并且您希望确保您的代码可以与其他没有这些额外方法的实现一起使用,则将该变量声明为基类型将确保您不要调用这些方法。
答案 2 :(得分:1)
调用a.Bark与d.Bark背后的目的是让你不需要知道对象的实际类型。通常,当您处理动物列表或者您正在编写将动物作为参数或返回参数但您不想使该方法特定于Dog类型对象的方法时,您会看到这一点。
查找有关多态性的一些信息,这些信息可以帮助您更好地理解。
答案 3 :(得分:0)
这个概念被称为'Programe到一个接口而不是一个实现',这里的接口并不意味着实际的c#接口它可以是一个基类,抽象类,它是一个非常流行的概念OO世界是“依赖注入”,“IOC(控制反转)”等其他概念的基础
就像埃里克已经说过的那样
如果你事先知道你实际上要创建一个Dog对象而不是使用基于Interfaced的技术影响较小但是当你使用返回Animal的Factory方法并且实际上直到Runtime不知道具体类型。
答案 4 :(得分:0)
你所看到的是继承的另一面。继承不仅仅是保存自己重写另一个类中存在的功能。
这个想法是,如果你正确地设计类层次结构,你可以在整个代码中以更安全的方式使用你的类(感谢C#是强类型的)。当然,重用可能用于整个对象系列的代码,而不是为每个类重写它。
让我们分析你给我们的例子的力量。
因为您有一个名为Animal的已知接口,所以您不需要知道整个程序中存在的所有动物类型(实现该接口的类)。
这允许您制作如下代码:
public interface Animal
{
void Play();
void WagTale();
void Eat(Food food);
}
}
void PlayWithAnimal(Animal animal) {
animal.WagTale();
this.ThrowBall();
animal.Play();
animal.WaTale();
}
对于实现该接口的任何其他动物类,无论如何实现,这都将起到相同的作用。
所以你可以这样调用这个方法:
Dog dog = new Dog();
Lion lion = new Lion();
Flee flee = new Flee();
PlayWithAnimal(dog);
PlayWithAnimal(lion);
PlayWithAnimal(flee);
同样,我们的想法是能够对您的类进行分类,并使用代码中使用相同方法和成员的最基本元素。
更面向C#的示例:Image
是一个抽象类,您甚至无法创建此类对象的实例。但是有许多其他类派生自Image
,因此虽然没有对象可以是真正的Image
,但您通常会在使用图像的代码中看到Image
。 (主要是图像实际上是Bitmap
或其他类)