首页 新闻 会员 周边

不太明白为什么抽象类可以定义常量,接口中不可以定义常量

0
[已解决问题] 解决于 2011-12-05 12:46

从内存的角度来说,是不是抽象类会分配内存,而接口不会呢。

不过,接口里那些函数的首地址总得需要内存空间的吧。

请大家帮我解开这个疑惑。

leon_ALiang的主页 leon_ALiang | 初学一级 | 园豆:194
提问于:2011-12-01 11:02
< >
分享
最佳答案
0

接口是一种契约,契约是不包含实现的。接口(契约)的含义就是,你要实现契约里的一些成员(包括属性/方法),至于你如何实现的我不管,只要有实现就可以。而类就是一种实现方式。抽象类之不过是某个类不能被直接实例化,它本身是可以包含实现的(比如你把一些逻辑实现在里面这样它的子类就不用实现了)。然后你说的分配内存的问题,要搞清楚“声明一个类/定义一个类”和“创建一个类的实例对象”两者的区别。

interface IFlyable
{
void Fly();
}
abstract class Bird : IFlyable
{
public void Fly() { }
}
class Plane : IFlyable
{
public void Fly() { }
}

以上只是声明了一些类/接口,并没有创建任何对象,因此并没有对这些对象实例分配内存*。

Plane p = new Plane();

这样才是创建对象,才会为对象分配内存。你说的“接口里那些函数的首地址总得需要内存空间的吧”是对的,当一个方法被执行的时候,CLR会检查当前方法用到了哪些类型。比如我上面那句,用到了IFlyable和Plane,他们的类型信息会在方法开始前被加载到内存中去。


水牛刀刀 | 大侠五级 |园豆:6350 | 2011-12-01 11:16

非常感谢@水牛刀刀的回复。

我明白接口的定义,比如在abstact class A中定义一个"const int i = 1", 在其他类中可以直接用A.i这个常量。

但假设接口也可以这样,在interface IB中也可以定义一个"const int i = 1", 在其他类中可以直接用IB.i这个常量。当然是不可以这样的现在。

为什么抽象类可以呢,是不是因为抽象类在运行时得到了该类的指针,通过偏移找到了i这个常量。而接口在内存中不存在指针,故无法找到i这个常量呢。

如何单从理论上接口的定义规范我明白不应该定义常量,但实现上有什么相悖的地方吗?我还是有些困惑。

leon_ALiang | 园豆:194 (初学一级) | 2011-12-01 11:34

@leon032: 如果你是想搞清楚这个的话,那我只能说“理论上接口也可以这么做的,但是感觉上不太对”,没有人说“接口不可以”,我相信如果微软团队想做成“接口可以”完全可以做到。那现在的问题是:有没有必要去做和这么做了对不对。在我看来完全没有必要让接口中也可以定义常量,因为没有哪种情况下是是有用的。如果你能想象到,你可以给我讲讲。

水牛刀刀 | 园豆:6350 (大侠五级) | 2011-12-01 11:50

@水牛刀刀: 上午有个同事在做一个维护的项目,需要一些常量。可能是之前的项目也不规范,他为了省事就想在之前的接口中定义一些常量。就是在这个问题上突然想到的一些有关接口中常量的东西。
如果说接口只是提供规范,是一些必须的规则,我觉得readonly的常理也能勉强算上吧。呵呵
总之,非常感谢回复!

leon_ALiang | 园豆:194 (初学一级) | 2011-12-01 12:48
其他回答(1)
0

1, 只有实体对象才会占用对象。

抽象类和接口都不能被实例化,所以讨论它们占用内存的问题没意义。

2, 要了解对象空间大小,建议你多了解一些“虚函数表(Virtual Table)”知识。

“虚函数表”讲深了很难,尤其是C++多继承,本人也只略知皮毛。但是多了解一点这方面的知识,对OO编程实践会有很大促进。

这方面的资料网上很多,随手一搜一大堆。

胡屯 | 园豆:714 (小虾三级) | 2011-12-01 11:36

感谢@胡屯的回复,我会仔细看看虚函数表的。

支持(0) 反对(0) leon_ALiang | 园豆:194 (初学一级) | 2011-12-01 12:44
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册