Java中的隐式对象类型?

时间:2011-02-04 20:29:18

标签: java casting polymorphism

这不完全是隐式类型转换的定义,但我很好奇我用这个标准打破了多少标准......

我在Java中创建一个抽象类,它基本上根据传递给构造函数的字符串来转换变量。

例如:

public abstract class MyClass {

    Object that;

    public MyClass(String input){
        if("test1".equals(input){
            that = new Test1();
        }
        else{
            that = new Test();
        }
    }

    public void doSomething(){
        if(that instanceof Test1){
            //specific test1 method or variable
        } else if(that instanceof Test2)}
            //specific test2 method or variable
        } else {
            //something horrible happened
        }
    }
}

你看到我得到了什么?现在我遇到的问题是我的编译器希望我在that方法中明确地将Test1转换为Test2doSomething - 我理解,因为编译器赢了'假设它是某种对象类型,即使if语句几乎保证了类型。

我想我得到的是,这是一个有效的解决方案吗?

我有其他类基本上都做同样的事情,但根据一个简单的差异使用两个不同的库,并且这个类可以帮助我轻松跟踪并对所有其他对象进行更改。

4 个答案:

答案 0 :(得分:10)

你是对的。这是在设计中实现多态性的可怕方法。你考虑过使用工厂吗?策略对象?听起来你想要实现的目标可以使用这些模式(以及其他模式)的组合以更松散耦合的方式实现。

对于doSomething的多态性,例如:

interface Thing {
    public void doThing();
}

class Test1 implements Thing {
    public void doThing() {
        // specific Test1 behavior
    }
}

class Test2 implements Thing {
    public void doThing() {
        // specific Test2 behavior
    }
}

class MyClass {

    Thing _thing;

    public void doSomething() {
        _thing.doThing();    // a proper polymorphism will take care of the dispatch,
                             // effectively eliminating usage of `instanceof`
    }
}

当然,您需要在一组公共接口下统一Test1Test2(以及其他具体Thing类,即现有和计划的)的行为。< / p>

PS:此设计通常称为Strategy Pattern

答案 1 :(得分:1)

我会创建一个单独的类文件。所以你会有这样的事情: 1.你抽象“MyClass” - &gt;在“MyClass”中定义一个抽象方法调用doSomething ...这将强制该方法的特定实现到它的子类。 2. Test1将是MyClass的实现,它将包含doSomething方法的实现 3.创建一个实用程序类,它执行检查“instanceOf”,检查不应该在它所属的构造函数中。

所以最后你会有3个类文件,一个Abstract类,Abstract的实现和一个执行“instanceOf”检查的类。我知道这听起来很多,但它是正确的设计方式,因为我认为你正在尝试做。你应该拿起一本设计模式书,我认为这对你有很多帮助。

答案 2 :(得分:1)

通过在此类之外移动对象创建,可以更好地满足Open-Closed principle

考虑更改构造函数以接受实现接口的对象。

public MyClass {
  public MyClass( ITest tester ) { m_tester = tester; }
  public void doSomething(){ m_tester.doTest(); }
}

这样就可以在不修改代码的情况下更改类的行为(打开扩展名)(关闭修改)。

答案 3 :(得分:1)

更好的方法是创建一个interface,它将指定一组可以保证在对象上调用的方法。

以下是一个例子:

public interface TestInterface
{
  void doTest();
}

现在您可以编写类来实现此接口。这意味着您需要为界面中的所有方法提供完整定义,在本例中为doTest()

public class Test implements TestInterface
{
  public void doTest()
  {
    // do Test-specific stuff
  }
}

public class Test1 implements TestInterface
{
  public void doTest()
  {
    // do Test1-specific stuff
  }
}

看起来真无聊,毫无意义,对吧?我听到你说很多额外的工作。

真值来自调用代码...

public abstract class MyObject
{
  Test that;

  // [...]

  public void doSomething()
  {
    that.doTest();
  }
}

不,如果陈述,没有实例,没有丑陋的块,没有。这一切都转移到了公共接口方法中的类定义(同样,这里是doTest())。