【问题标题】:Java Inheritance on the fly即时Java继承
【发布时间】:2017-03-16 06:11:34
【问题描述】:

让 ClassA 代表一个抽象类。

我想知道是否可以在 Java 中做这样的事情:

public static abstract class ClassA {
    abstract void foo();
}

private ClassB extends ClassA a = new ClassA() {
     // define abstract methods here
     foo() { System.out.println("in anon!"); }

     // define OTHER variables here
     public int varB = 10;
}

// later... varB is not defined in ClassA, but it is in a.
// how can I access varB from a?
System.out.println(a.varB);

我想特别说明一下:注意我是如何打印 varB 的。假设 varB 未在 ClassA 中定义,仅在匿名内部类中。

我有很多抽象类,我在创建它们时动态定义它们的抽象方法。但是,我也想将这些类视为它们自己的类型,因为有时我需要访问该类中特定于该对象版本的变量。

有没有办法做类似于我上面展示的事情,或者我是否需要创建一个每次都从“ClassA”扩展的“ClassB”?

是否有某种解决方法?

谢谢

【问题讨论】:

  • 我想我找到了你要找的东西,我已经更新了我的答案。
  • 不使用反射是不可能的。
  • 嗯,是的,似乎唯一的方法是使用反射或定义类继承。

标签: java class inheritance abstract-class


【解决方案1】:

试试Java Anonymous inner classes。示例如下:

abstract class ClassA {  
 abstract void eat();  
}  
class TestAnonymousInner{  
 public static void main(String args[]){  
  ClassA p=new ClassA (){  
    void eat(){System.out.println("nice fruits");}  
  };  
  p.eat();  
}  
}  

EDIT:

就访问变量varA而言,您需要在抽象类声明该变量,因为ClassA需要有关该变量的信息.这里我们可以将p所引用的对象视为ClassA的子类,该子类由其父类引用,因此父类无法访问子类中引入的方法和变量(在此以匿名类为例)。

【讨论】:

  • 我的问题是,如果我在新的匿名类中创建了一个名为“varA”的新变量,即使我将“varA”公开,我也无法访问 varA 就像我会“吃”一样。
  • @Luca,请找到已编辑的部分,如果抽象类定义中没有提及eat(),您甚至无法访问。
【解决方案2】:

匿名类不适合您的用例吗?

public static void main(String[] args) {
    // Make an anonymous instance of A
    final A first = new A() {
        private final int i = 10;

        void foo() {
            System.out.println(i);
        }
    };

    // Make another anonymous instance of A
    final A second = new A() {
        private final String message = "Listen!";

        void foo() {
            System.out.println("Hey!");
            System.out.println(message);
        }
    };

    // They do their own unique things
    first.foo();
    second.foo();

    // Both have A as a super-type
    System.out.println(first instanceof A);
    System.out.println(second instanceof A);

    // But first and second are *not* A and therefore not the same class!
    final boolean isSameClass = first.getClass().equals(second.getClass());
    System.out.println(isSameClass);
  }

  static abstract class A {
     abstract void foo();
  }

这里的想法是,当您创建一个新的匿名类时,您实际上是在对您用于单个实例的类进行子类型化。这就是为什么双括号初始值设定项是一个坏主意的部分原因!

编辑:访问仅属于匿名类is not possible 的变量。但是,如果你对反射没意见,这样的事情可能会起作用:

try {
    final Field i = first.getClass().getDeclaredField("i");
    i.setAccessible(true);
    System.out.println(i.getInt(first));
} catch (NoSuchFieldException | IllegalAccessException e) {
    e.printStackTrace();
}

这很混乱,我不一定会推荐它,但它确实完成了你在这里要做的事情。

【讨论】:

  • 我已经编辑了我的帖子以使事情更清楚。想象一下,我正在尝试从外部访问特定于该匿名实例化的变量或方法。
  • 不幸的是,这是静态类型的限制。你可以在这里阅读更多信息:stackoverflow.com/questions/6459298/…
  • 啊。非常感谢参考! :)
【解决方案3】:

您可以在方法中本地定义一个新类。

我在方法main 中添加了一个新类MixA。只是为了看看它是如何工作的,这个类扩展了一个抽象类 ClassA 并实现了一个接口 AInterface 但你不需要这样做,只需扩展或实现你需要的。

因此,如果定义了类,您可以在编译时找到您添加的每个方法或公共:

abstract class ClassA {
  abstract void doThis();
}

interface AInterface {
  public int getInternalValue();
}

public class TestAnonymousInner {
  public static void main(String args[])
  {

     class MixA extends ClassA implements AInterface {

      public int varB = 10;

      @Override
      public int getInternalValue()
      {
        return 0;
      }

      @Override
      void doThis()
      {
      }

    }

    MixA b = new MixA();    
    b.getInternalValue();
    b.doThis();

    System.out.println(b.varB);

  }
}

【讨论】:

  • 我明白,但问题是我想要访问 varB,即使它没有在 AClass 或 AInterface 中定义。
猜你喜欢
  • 2020-04-14
  • 2012-10-30
  • 2017-12-27
  • 1970-01-01
  • 2011-03-31
  • 1970-01-01
  • 2012-02-25
相关资源
最近更新 更多