由于每个类都是从system.object派生的,派生类对象是否引用其层次结构中的类? (当然只有他们上面的课程)
例如
public class A
{
//contains some attributes and methods
}
public class B: A
{
//contains some attributes and methods
}
public class C: B
{
//contains some attributes and methods
}
现在 OBJECT OF CLASS“C”是指A,B以及system.object类吗?
答案 0 :(得分:6)
我花了一段时间,但我发现了。 您认为C#是“原型继承”语言。它不是。
在原型继承语言(如JavaScript)中,每个对象都有对其“原型对象”的引用。所以在JavaScript中你可能会说:
function Dog() {}
Dog.prototype.legs = 4;
var rover = new Dog();
var spot = new Dog();
spot.legs = 3; // Poor spot!
print(rover.legs); // 4
print(spot.legs); // 3
rover
和spot
都有引用到Dog.prototype
。当你问rover
“你有多少条腿?” rover
说“我不知道;让我问我的原型”。 rover
本身引用的对象引用了Dog.prototype
引用的对象,并且该属性具有legs
属性。
当你问spot
“你有多少条腿?”时,spot
也有对其原型的引用,但它不需要它,因为spot
已经知道了它有多少腿。
通过更多的工作,我们可以构建一个系统,其中Dog.prototype
的原型是“Animal
原型对象”。然后链条将继续; rover
会引用Dog.prototype
,Dog.prototype
会引用Animal.prototype
,而Animal.prototype
会引用Object.prototype
。< / p>
C#根本不起作用。在JavaScript中,对象是原型链表的一部分,当需要查找属性时会搜索原型链。在C#中,每个属性的所有信息都存储在的每个实例中。在C#中,对象不引用其基类型的实例,并且不包含其基类型的实例;相反,它继承其基类型的所有成员。 (除了构造函数和析构函数。)
答案 1 :(得分:1)
通过阅读评论,您的误解似乎是当您创建C类实例时,还有B,A或Object类的单独实例。事实并非如此。有一个对象是C类的实例,它也可以被视为B类,A类或Object类的实例(在Liskov Substitution Principle上读取)。修改Eric Lippert的类比:当狗被创造(出生)时,它是狗,哺乳动物和动物。但是只有一只狗。
考虑这个(动物,哺乳动物,狗,而不是A,B,C):
public class Animal
{
void Breathe();
}
public class Mammal : Animal
{
void GrowHair();
}
public class Dog
{
void Bark();
}
此继承链具有以下效果:
public class C
{
void Breathe();
void GrowHair();
void Bark();
}
就字段而言,回到A,B,C,请考虑以下事项:
public class A
{
private int _a;
}
public class B: A
{
private int _b;
}
public class C: B
{
private int _c;
}
A的实例如何在内存中查找?一些字节的开销,加上_a
的四个字节:
OVERHEAD
_a : four bytes
B的实例如何在内存中查找?它看起来就像A的一个实例加上四个字节:
OVERHEAD
_a : four bytes
_b : four bytes
C的实例看起来像A的一个实例加上八个字节:
OVERHEAD
_a : four bytes
_b : four bytes
_c : four bytes
那是什么开销?毫不奇怪,这是Object
类定义的东西!所以每次在继承链中添加另一个类时,该类中定义的字段只会被添加到内存的末尾。其父类的结构。
派生类的实例不会引用其父类定义的数据;它包含由其父类定义的数据。
答案 2 :(得分:0)
C类型的对象也可以是B,A和System.Object
类型。
它将包含它继承的其他类的所有成员(公共或受保护的方法,属性和字段)。这就是为什么所有对象都有“ToString”方法 - 它们从System.Object
继承它。
答案 3 :(得分:0)
是。默认情况下,所有类都隐式引用system.object类。
答案 4 :(得分:0)
不完全是,但它比其他任何东西都更具语义性。
C类的对象是指名为C的类定义的实例。但是,它可以被类型转换为对象键入A,B或只是普通的旧System.Object。
C和A / B / System.Object之间没有“引用”。它更像是将所有这些类定义合并为一个统一的“C”。
这意味着您可以执行以下操作:
function void DoSomething(A input) {
// do something as A
}
C myObj = new C();
DoSomething(myObj);
在上面的例子中,C将在DoSomething调用中被类型转换为A类对象。
您还可以执行以下操作:
public class A {
public String MyValue { get; set; }
}
public class B : A{
public String AnotherValue { get; set; }
}
public class C : B {
public void DoSomething() {
MyValue = "Hello";
AnotherValue = "World";
}
public String Output() {
return String.Format("{0} {1}", MyValue, AnotherValue);
}
}
C myObj = new C();
C.DoSomething();
String message = C.Output();
// value of message will be "Hello World"
现在情况正好相反。您无法执行以下操作:
function void DoSomething(C input) {
// do something as C
}
A myObj = new A();
DoSomething(myObj);
在这种情况下,您将遇到编译器错误。