C#创建类和派生类的实例

时间:2013-11-05 07:52:30

标签: c# .net oop inheritance polymorphism

我在c#程序中尝试了以下代码。这只是为了学习OOPs概念。

 class a
    {      
        public void testa()
        {
        }
    }
    class b:a
    {     
        public void testb()
        {
        }
    }

  a a1 = new b();

  b b1 = new a();

我对上述代码有以下疑问。

  1. 为什么我在第二行遇到错误?
  2. a a1=new b();
  3. 的含义
  4. 即使a1.testb()的构造函数已分配给b,为什么a1无法访问?
  5. a a1=new a()a a1=new b()之间的区别是什么?

6 个答案:

答案 0 :(得分:3)

1)如果你的意思是这一行:

b b = new a();

这是因为每个b都是a,但不是每个a都是b

2-3)a a1=new b();的含义是什么      即使a1.testb()的构造函数已分配给b,为什么a1无法访问?

这意味着您创建了b类的对象,但是将其引用为a(您可以通过此引用将其视为a,即使它是b }})

答案 1 :(得分:2)

我将您的类和方法名称更改为真实世界,以便更好地理解。我将a命名为Animal,将testa命名为Eat,将b命名为Human,将testb命名为Talk 。所以我们有:

class Animal {      
    public void Eat() { }
}

class Human : Animal {     
    public void Talk() { }
}

Animal a1 = new Human();

Human b1 = new Animal();

好的,回到你的问题。

1)你在第二行得到错误,因为每只动物都不是人类。是吗?

2)a1=new b()根据我们新的命名惯例,转为a1 = new Human,这意味着Animal a1 = new Human。所以,这是正确的,因为人类是一种动物。

3)a1.testb()根据我们新的命名惯例,转为a1.Talk()。好吧,a1是动物(Animal a1),我们不能指望动物说话。

更多

认为class是一组属性和行为。例如,我们有一个名为Animal的组,用于定义Eat行为。另一个名为Human的组扩展了Animal组,并且它有自己的行为,名为Talk。众所周知,Human也有其超群体行为 - 例如。在此示例中为Eat - 。

当我们有一个小组Animal的实例时,我们可以期待它吃。但我们不能要求它说话。这是不可能的。另一方面,我们从组Human中选择的每个项目实际上都是Animal。所以我们可以请他吃饭。

如果我们有Human个实例,我们可以让他表现为HumanAnimal。我的意思是,我们可以问他Talk,我们也可以问他Eat。每个Human可以位于人类组和动物组中。

1)当我们说Human b1 = new Animal();时,它确切地说:从Animal组中获取项目 - 右侧部分 - 并将其放入Human组 - 左侧部分 - 这是不可能的。因为有很多动物不是人类。

2)当我们说Animal a1 = new Human时:从Human组中获取一个项目 - 右侧部分 - 并将其放入Animal组 - 左侧部分 - 这很容易实现。

3)当我们说a1.Talk()时,我们希望Animal能够说话。我的意思是我们希望Animal行为Human行为是不可能的。

答案 2 :(得分:2)

可能继承多态概念对您来说还不是很清楚。 This article可能会对您有所帮助。

如果班级b继承自a,您可以将其视为a的“专业化”。 因此,您可以很容易地理解b可以被用作/看作a实例,但反之则不然!


  

为什么我在第二行遇到错误?

因为b b1 = new a();不是有效的作业。如上所述,您可以将继承的类实例分配给基类变量,但不能相反!

  

a1 = new b();

是什么意思

这个赋值是正确的,因为你肯定可以使用更具体的类实例作为基类实例。

  

为什么a1.testb()无法访问,即使将b的构造函数分配给a1?

当您从类继承时,此类的所有publicprotected方法都将被继承,您可以在新类中访问或覆盖它。但testb()不是继承的方法。是在类b中定义的新方法,因此只有在执行此分配时才能使用它:b b1=new b();

答案 3 :(得分:1)

如果你定义了a1 = new b(),要使用b中声明的方法,你可以将a1转换为b

 a a1 = new b();
 ((b)a1).testb();

答案 4 :(得分:1)

将您的课程视为合同,保证某些操作的存在。 类a定义了一个操作,类b继承了a的所有操作,并定义了另一个操作。

第一行:

a a1 = new b();

声明一个名为a1的{​​{1}}类型的变量,这意味着你赋予的任何值,这个变量应该具有a所需的所有操作。 a创建了一个新的类new b()实例,该实例已分配给变量b。由于类a1继承了类型b中的所有操作,因此可以将类型a的值分配给类型为b的变量。

在第二行:

a

类似地,您定义一个变量,该变量应具有由b b = new a(); 类型定义的所有操作。但是,由于您输入了b类型的值,该值未定义a操作类型testb所需,因此编译器不接受此操作。

关于第三个问题,编译器只知道变量的类型(b),而不知道实际分配给它的值。你基本上告诉编译器“我保证这个值将定义a操作。现在让它进行操作testa!”编译器不知道变量的实际值,因此就其而言,这是不可能的。

至于testba a1=new a()之间的差异: 在这两种情况下,都会创建一个a a1=new b()类型的变量。在第一个表达式中,分配给此变量的值是新创建的类型a的实例,而在第二个表达式中,该值是新创建的类型a的实例。由于类型“b”基本上是类型b的扩展版本,因此编译器知道类型a的实例也可以满足您对a类型实例的所有要求。 ,所以它只是将值视为b类型。

答案 5 :(得分:0)

1)每个b都是a,但相反的情况并非如此。

2)是多态性Polymorphism - Define In Just Two Sentences

的一个例子

3)a1.testb()无法访问,因为您将其视为a的实例,其中没有testb()的定义