我有2节课。我们称它们为A类和B类.A类包含一个执行某些动作的方法。 B类使用自己的版本覆盖此方法,但会在A类中对该方法进行super
调用以执行操作。现在,这工作正常。但是,如果对象仅一个类A的实例,那么只有在A类中才会执行一些操作。换句话说,如果对象是,则不应该在A类方法中执行某些操作。 A类儿童的一个实例。
目前,我正在使用instanceof
来检查每个孩子,但我需要指定每个子类,因此如果以后添加新子项,则需要更新此方法。我想要的是一种确定对象是否是子类的动态方法。
有没有好的选择,或者instanceof
还有什么路要走? p>
public class A{
public void someMethod(){
// Only perform these actions if it is not a child class. This is what
// I am looking for a better solution for
if(!(this instanceof B)){
// Some action...
}
// Actions to execute for every call
}
}
public class B extends A{
@Override
public void someMethod(){
super.someMethod();
// More actions
}
}
正如对设计的解释一样,我用它来生成XML。在程序中,我有List<A>
来存储数据。当需要输出XML时,我遍历列表并调用generateXML
(someMethod
在我的示例中占据了它的位置。)
创建A类对象时,需要将其数据放在<A></A>
个标记内。创建B类对象时,需要将其数据放在<B></B>
个标记内。但A
的所有属性也必须位于<B></B>
标记内,因此现在它调用的对象只有generateXML
对象时使用的A
方法}
但正如其他人所指出的那样,调用同样的方法并不是可行的方法。类B
应该在类A
中调用受保护的方法,该方法仅生成必要的信息。
答案 0 :(得分:7)
创建执行特定于类的事物的受保护方法,并从someMethod()调用它们。 A类将提供其实现,如果子类需要有效地删除该代码,那么它可以使用空实现覆盖受保护的方法。
不要对抗多态性;使用它对你有利。
示例:
public class A {
protected void someOtherMethod() {
// Do stuff specific to A here.
}
public void someMethod() {
// Do some stuff
someOtherMethod();
// Do some more stuff
}
}
public class B extends A {
@Override
protected void someOtherMethod() {
// Empty implementation; B doesn't need to do this.
// Or do stuff specific to B...
}
}
答案 1 :(得分:3)
那么现在这是一个可怕的设计,应该以不同的方式解决(例如,让从子类调用的部分成为一个自己的受保护方法),但如果你真的需要它,你可以检查
this.getClass()== A.class以查看该类是否真的相同。
答案 2 :(得分:1)
我认为instanceof
是一个使用多态的机会。
保持所有类型someMethod
的{{1}}共同行为。子类A
用于实现您当前使用A
检查的行为。
instanecof
答案 3 :(得分:1)
为什么不:
public class A{
public void someMethod(){
// Only perform these actions if it is not a child class. This is what
// I am looking for a better solution for
if(this.getClass().equals(A.class))
// Some action...
}
// Actions to execute for every call
}
}
和
public class B extends A{
@Override
public void someMethod(){
super.someMethod();
// More actions
}
}
答案 4 :(得分:1)
这可能与cdhowie试图说的相同。 (没有冒犯:我认为你有点不清楚。)
不要使用instanceof。而是创建返回给定类型的标志或其他适当值的方法。
你的例子没有提供你想要做什么的任何细节,所以我只是发明了一些东西。
!!!错误的方式!!!
public class Car
{
public void goUphill()
{
// XYZ has automatic transmission -- don't need to downshift
if (!(this instanceof XYZ())
{
downshift();
}
pressGas();
}
}
public class ModelXYZCar extends Car
{
public void goUphill()
{
tellWifeToGetOutAndPush();
super.goUphill();
}
}
更好的方式:
public class Car
{
public boolean isManualTransmission()
{
// default
return true;
}
public void goUphill()
{
if (isManualTransmission())
{
downshift();
}
pressGas();
}
}
public class ModelXYZCar extends Car
{
public boolean isManualTransmission()
{
return false;
}
public void goUphill()
{
tellWifeToGetOutAndPush();
super.goUphill();
}
}
这样,超类不必知道子类需要什么。每个子类定义自己的行为。在这种情况下,每个子类定义一个isManualTransmission函数,并在适当时返回true或false。
更好的是避免使用标志并在每个类中放置适当的行为:
abstract public class Car
{
abstract public void downshift();
public void goUphill()
{
downshift();
pressGas();
}
}
public class AutomaticTransmissionCar extends Car
{
public void downshift()
{
// Automatic transmission -- no need to do anything
}
}
public class ManualTransmissionCar extends Car
{
public void downshift()
{
... whatever ...
}
}
public class ModelXYZCar extends ManualTransmissionCar
{
public void goUphill()
{
tellWifeToGetOutAndPush();
super.goUphill();
}
}
答案 5 :(得分:0)
只有当这是A类的实例时,表达式A.class.equals(this.getClass())
才返回true。如果是子实例,则结果将为false。
但是:如果你必须这样做,请检查你的设计。听起来非常不是面向对象的风格。我可以给你一个替代方案。将基类A分为2:真正的基类A0及其子A1。你的B级将是A1的兄弟,并将直接从A0延伸。
在这种情况下,您可以将公共代码放入A0类,并将所有特定代码(在您的版本中必须仅在类完全是A而不是其子类时执行)到A1。
答案 6 :(得分:0)
我可能会弄错,但你的情况似乎是“赞成合成而不是继承”和“封装不同的东西”的理想场景。在像你这样的情况下,一般的行动方针是:
在B,C等中创建A的实例并调用A.someMethod()。
public class A {
public void someMethod(){}
private void someOtherMethod(){
// move behavior specific to A in here.
}
}
public class B { // no extends
public void someMethod() {
new A().someMethod();
}
}
同样,我可能错了,这可能不适用于你的情况。
答案 7 :(得分:0)
“call super”is an anti-pattern。而不是期望子类调用超类功能,而是反过来。现在,超类完全控制了“普通”之前和之后所谓的内容。
public class A {
public void someMethod() {
beforeCommonStuff();
// Actions to execute for every call
afterCommonStuff();
}
protected void beforeCommonStuff() {
// Actions to execute only for class A
}
protected void afterCommonStuff() {}
}
public class B extends A {
@Override
protected void afterCommonStuff(){
// More actions
}
}