编程时,我们通常使用一些类型转换操作。
当铸件发生在“同一级别”的物体上时,感觉还可以。但当它发生在“不同层面”(主要是父子之间)的对象上时,感觉很奇怪。
考虑到这一点:
Class Son extends Father
当Son s = (Son)father;
时,这绝对是不合理的。因为“儿子”不再是“父亲”,“儿子”可能会成长为“父亲”没有的一些新属性,所以施放操作使这些属性不为人知。
另一方面,Father f = (Father)son
似乎是合理的,但根据LSP
“派生的实例应该能够替换其超类的任何实例”
“儿子”可以做任何他的“父亲”可以做的事情,所以施法操作似乎毫无用处。
那么我可以说这些铸造操作是非常好的OO设计原则但是必要吗?
答案 0 :(得分:2)
我发现像这样的问题总是很有趣,它有助于我认为的某种辩论:)
以下是我的想法。 在课堂设计中,我会在这种情况下创建一个Person
类class Person
{
public bool IsFather { get; set; } // this variable will change depending on the count of children
public List<Person> children { get; set; }
}
当我创建派生类时,该类应该是一个专门的人,在父和子的情况下,我不会创建一个父类和一个Son类。
答案 1 :(得分:2)
在OOP中转换对象通常是类继承或接口继承的产物。必须要记住,类继承表示“是一个”关系,接口继承表示“有一个”关系。
让我们回到你的例子:Class Son extends Father
听起来不是一个合理的抽象,因为每个男性都是儿子,但不是所有男性都是父亲。事实上,相反的情况可能更适用:Class Father extends Son
因为每个父亲都是某人的儿子。
另一方面,我们可以放弃整个抽象,并说我们有一个Class Person
,可以是男性或女性,母亲或父亲,等等。每个人都有一个属性,其中包含名为Person
的{{1}}集合。
在此抽象中,如果Children
的性别为男性且Person
,则Father
将仅被视为Person.Children.Count > 0
。这比在其中定义Father
类要简单得多。
答案 2 :(得分:1)
你有一个糟糕的继承例子。
更好的可能是
Class Person
{
public void walk();
}
Class Man extends Person
{
public void shaveBeard();
}
继承是表示是关系的方式;例如“Man
是Person
”。
这些行中的任何一行都可以。
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();
}
答案 3 :(得分:0)
对我来说似乎都不合理。似乎更合理的是:
Son s = (Son)person //Valid
Father f = (Father)person //Valid
答案 4 :(得分:0)
这是一个提示:左侧的类是超类,而右侧的类是子类,所以如果我们有这个: 对象p = new Student(); //是正确的 Student s = new Object()//错了......就像说每个Object都是学生.. 在进行显式转换时必须小心,因为它可能看起来正确但可能无法按预期工作。你不能自己实例化你父亲的私有财产。