2010-05-28 42 views
3

编程时,我们通常使用一些类型铸造操作。有关OOP中“铸造操作”的问题

当铸件发生在“同一层”的物体上时,感觉没问题。但是当它出现在“不同层次”的主体(主要是父子之间)时,感觉很奇怪。

考虑到这一点:

Class Son extends Father 

Son s = (Son)father;,这是绝对不合理的。因为“儿子”不再是“父亲”了,“儿子”可能会伴随着“父亲”所没有的一些新属性而长大,铸造操作使得这些属性不为人知。

在另一方面,Father f = (Father)son似乎是合理的,但根据LSP

“衍生的一个实例应该能够取代它的超类的任何实例”

A“儿子”可以做他的“父亲”所能做的任何事情,所以铸造操作似乎毫无用处。

所以我可以说这些铸造操作是恶性的OO设计原则,但必要的?

回答

2

在OOP中投射对象通常是类继承或接口继承的产物。人们必须始终记得,类继承表示“是”关系,并且接口继承表示“有”关系。

让我们继续看你的例子:Class Son extends Father听起来不像一个合理的抽象,因为每个男性是儿子,但并不是所有的男性都是父亲。事实上,相反可能更适用:Class Father extends Son,因为每个父亲总是人的儿子。另一方面,我们可以忽略整个抽象,并说我们有一个Class Person,可以是男性或女性,也可以是母亲或父亲,等等。每个人将有一个属性,其中包含Person的集合,其名称为Children

在这个抽象中,如果Person的性别是男性,并且Person.Children.Count > 0只被认为是Father。这比单独定义一个Father类要简单得多。

+0

我想我们有同样的想法:)我只是忘了性别,愚蠢的性别:P – 2010-05-28 05:30:01

2

我找到像这总是很有趣的问题,它本身借给某种辩论,我认为:)

这里是我的想法。 在一流的设计我想在这种情况下,创建一个类人

class Person 
{ 
    public bool IsFather { get; set; } // this variable will change depending on the count of children 
    public List<Person> children { get; set; } 
} 

当我创建一个派生类,类应该是一个专业的人,在父亲和儿子的情况下,我不会创建父亲班和儿子班。

0

这对我来说似乎不合理。什么似乎更合理:

Son s = (Son)person   //Valid 
Father f = (Father)person //Valid 
1

你有一个不好的例子继承。

一个更好的可以是

Class Person 
{ 
    public void walk(); 
} 
Class Man extends Person 
{ 
    public void shaveBeard(); 
} 

继承是表示一个关系的方式;例如“a ManPerson”。

使用这些线路的对象

要么是OK。

Person p = new Person(); 
Person m = new Man(); 

这是罚款,呼吁两国p.walk。但是要调用shavebeard()方法,m必须是Man对象。由于类型安全的原因,您必须将其投射到一个Man对象;例如(Man) m.shaveBeard();演员在这里会失败,所以最好检查变量是指Man一个实例:

if(m instanceof Man) 
{ 
    (Man) m.shaveBeard(); 
} 
0

这里有一个提示:在左侧的类是超类,并且在右侧子类,所以如果我们有这个: 对象p = new Student(); //是正确的 学生s = new Object()//是错误的......这就像说每个对象都是学生.. 在进行显式转换时必须小心谨慎,因为它可能看起来是正确的,但可能无法按预期工作。你不能将你父亲的私人财产实例化给你自己。