3

我在我的 c# 程序中尝试了以下代码。这仅用于学习 OOP 概念。

 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. 为什么a1.testb()即使将构造函数b分配给也无法访问a1
  4. a a1=new a()和有什么区别 a a1=new b()
4

6 回答 6

4

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

b b = new a();

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

2-3)a a1=new b(); 为什么a1.testb()即使构造函数b被分配给也无法访问是什么意思a1

这意味着您创建了b类的对象,但将其引用为a(您可以通过此引用处理它,而无需仅按原样进行a转换b

于 2013-11-05T07:56:21.293 回答
4

我将您的类和方法名称更改为真实世界的等效名称,以便更好地理解。我将其命名a为 as Animaltestaas EatbasHumantestbas 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),我们不能指望动物会说话。

更多的:

认为aclass是一组属性和行为。例如,我们有一个名为Animal定义Eat行为的组。另一个名为Human扩展Animal组的组,它也有自己的行为,名为Talk. 正如我们所知,Human它也有它的超群行为——Eat例如在这个例子中——。

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

当我们有一个Human实例时,我们可以要求他表现得像 aHumanAnimal太。我的意思是,我们可以要求他这样做Talk,我们也可以要求他这样做Eat。每个Human都可以位于人类组和动物组中。

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

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

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

于 2013-11-05T08:12:09.077 回答
3

可能继承多态的概念对你来说还不是很清楚。 这篇文章可能会对你有所帮助。

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


为什么我在第二行出现错误?

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

a1=new b() 是什么意思;

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

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

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

于 2013-11-05T09:17:53.433 回答
1

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

 a a1 = new b();
 ((b)a1).testb();
于 2013-11-05T07:59:13.647 回答
1

把你的类想象成一个契约,保证某些操作的存在。类a定义一个操作,类b继承所有操作a并定义另一个自己的操作。

第一行:

a a1 = new b();

声明一个名为a1type的变量a,这意味着你给这个变量的任何值都应该具有类型a所需的所有操作。new b()创建一个新的 class 实例b,该实例分配给 variable a1。由于 classb继承了 type 的所有操作,因此可以将 typea的值b分配给 type 的变量a

在第二行:

b b = new a();

同样,您定义一个变量,该变量应具有 type 定义的所有操作b。但是由于您输入了一个a未定义testb操作类型b所需的类型值,因此编译器不接受这一点。

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

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

于 2013-11-05T08:09:38.913 回答
0

1) 每一个b都是一个,a但反之不成立。

2) 是多态性的一个例子多态性 - 仅用两句话定义

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

于 2013-11-05T07:59:15.803 回答