【问题标题】:A method to take a number of types一种获取多种类型的方法
【发布时间】:2023-04-07 03:34:01
【问题描述】:

我目前正在使用一个接受对象类型的构造函数 然后我根据 instanceof 测试它的类型

Public MyClass (Object obj)
{
if(obj instanceof CusClass1){
CusClass1 myObject = (CusClass1) obj;
globalVar1 = myObject.getAttrib1();
globaVar2 = myObject.getAttrib2();
}
if(obj instanceof CusClass2){
CusClass2 myObject = (CusClass2) obj;
globalVar1 = myObject.getAttrib1();
globaVar2 = myObject.getAttrib2();
}
}

这可以偏移到从构造函数中调用的初始化方法吗?主要问题在于对象的铸造。我一直认为重复的代码是糟糕的代码。这可以做得更优雅吗?

【问题讨论】:

    标签: java constructor variable-assignment


    【解决方案1】:

    一个更好、更安全的设计是创建多个重载的构造函数。这样您就不需要任何强制转换,并且您将无法通过传递一个不适当类型的对象来构造一个对象。

    public MyClass(CusClass1 myObject) {
        globalVar1 = myObject.getAttrib1();
        globalVar2 = myObject.getAttrib2();
    }
    
    public MyClass(CusClass2 myObject) {
        globalVar1 = myObject.getAttrib1();
        globalVar2 = myObject.getAttrib2();
    }
    

    CusClass1 和 CusClass2 是否具有相同的 getAttrib1() 和 getAttrib2() 方法?然后考虑创建一个这两个类都实现的接口,并创建一个构造函数,该构造函数接受一个实现该接口的对象:

    public interface Attribs {
        String getAttrib1();
        int getAttrib2();
    }
    
    public class CusClass1 implements Attribs {
        // ...
    }
    
    public class CusClass2 implements Attribs {
        // ...
    }
    
    public class MyClass {
        // You can now pass anything that implements interface Attribs
        public MyClass(Attribs myObject) {
            globalVar1 = myObject.getAttrib1();
            globalVar2 = myObject.getAttrib2();
        }
    }
    

    【讨论】:

    • 他们有相同的方法不幸的是他们不在我的编辑范围内:(
    • 它们是否基于接口尚不清楚?或者你知道他们没有实现接口?
    【解决方案2】:

    改为为每种类型的对象创建一个方法。

    public MyClass(CusClass1 obj) {
        field1 = obj.getProperty1();
        field2 = obj.getProperty2();
    }
    
    public MyClass(CusClass2 obj) {
        field1 = obj.getOtherProperty1();
        field2 = obj.getOtherProperty2();
    }
    

    【讨论】:

      【解决方案3】:

      不要重复代码,不要强制转换。创建 2 个构造函数:一个接受 CusClass1,第二个接受 CusClass2。分别实现它们。

      【讨论】:

        【解决方案4】:

        如果您有许多这样的自定义类,最好使用反射和/或注释(尤其是如果在编译时并非所有这些类都是已知的,这可能是唯一的解决方案)。

        如果所有自定义类都具有相同名称的必要属性/方法(例如您的示例中的attrib1 和attrib2),则反射更容易。您所需要的只是一组潜在的类名,以及要查询的属性的名称。

        但是,如果属性名称可能不同,您可以考虑使用注解在每个类中标记所需的源属性。

        【讨论】:

          【解决方案5】:

          如果你可以修改CusClass1和CusClass2,你可以创建一个接口

           public interface AttributeProvider {
               Object getAttrib1();  // or whatever type getAttrib1 should return
               Object getAttrib2();
           }
          

          然后确保CusClass1和CusClass2实现这个接口:

           public class CusClass1 implements AttributeProvider {
               ...
           }
          

          那么你可以有一个只有那个接口的构造函数:

           public MyClass(AttributeProvider myObject) {
               globalVar1 = myObject.getAttrib1();
               globaVar2 = myObject.getAttrib2();
           }
          

          这样,如果你创建一个新的CusClass3,你就不必修改MyClass,它也应该在MyClass中使用

          【讨论】:

            【解决方案6】:

            如果您的构造函数可以修改为接受 CusClass1 和 CusClass2 而不是 Object,那么您可以遵循其他答案中提供的解决方案之一。

            否则,是的,你可以像这样使用 init 方法:

            public class MyClass {
            
                public MyClass (Object obj) {
                    if (obj instance of CusClass1) {
                     init((CusClass1) obj);
                    } else if (obj instanceof CucClass2) {
                     init((CusClass2) obj);
                    }
            
                    // shared initialization code
                }
            
                public void init(CusClass1 obj) {
                    globalVar1 = obj.getAttrib1();
                    globaVar2 = obj.getAttrib2();
                }
            
                public void init(CusClass2 obj) {
                    globalVar1 = obj.getAttrib1();
                    globaVar2 = obj.getAttrib2();
                }
            }
            

            【讨论】:

            • 是的,你是对的。我以为 CusClass1 和 CusClass2 有不同的属性。
            • 所有其他解决方案都有类似的重复代码,除了建议使用接口的那个。
            • 是的。除非接口是可接受的解决方案,否则某些设计模式可能会派上用场。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2016-09-20
            • 2011-10-06
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-04-08
            相关资源
            最近更新 更多