Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/arduino/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在超类构造函数中调用抽象方法_Java_Superclass - Fatal编程技术网

Java 在超类构造函数中调用抽象方法

Java 在超类构造函数中调用抽象方法,java,superclass,Java,Superclass,我在super的构造函数中有一个抽象方法调用。我遇到错误“构造函数调用必须是构造函数中的第一条语句”,因为在调用super的构造函数之前,我需要初始化子类中的某些状态 我知道构造函数调用必须是第一个。。但这让我有些问题 我的超类中有一个抽象方法,所有子类都实现自己。 但是子类构造函数需要在运行抽象方法之前必须处理的参数 在我的代码中,我在超类构造函数中使用了抽象方法,因此您当然会理解这个问题: 超级课堂: 使用super(i1,i2)获取info1和info2 通过子类执行抽象方法 但是,超类构

我在super的构造函数中有一个抽象方法调用。我遇到错误“构造函数调用必须是构造函数中的第一条语句”,因为在调用super的构造函数之前,我需要初始化子类中的某些状态

我知道构造函数调用必须是第一个。。但这让我有些问题

我的超类中有一个抽象方法,所有子类都实现自己。 但是子类构造函数需要在运行抽象方法之前必须处理的参数

在我的代码中,我在超类构造函数中使用了抽象方法,因此您当然会理解这个问题: 超级课堂:

  • 使用super(i1,i2)获取info1和info2
  • 通过子类执行抽象方法
  • 但是,超类构造函数几乎不知道它还需要info3和info4,它们在下面的行中声明 超级()行

    我一直在想办法让超类构造函数返回并收集子类的信息 它执行这个方法,但我什么都没想到

    此外,该方法不能要求参数,因为所有子类的抽象方法的参数都不同

    你们这些有经验的人,我该如何应对

    在谷歌搜索之后,这似乎与此有关:

    但他还是个新手,所以很难坚持下去。。 我觉得如果在处理子类构造函数之后使用super()就可以避免所有这些麻烦

    按要求编码:

        abstract public class Prylar {
          abstract public Integer value();
    
          private String itemName;
          private Person owner;
    
    
          public Prylar(Person thisOwner, String iN){
          owner = thisOwner;
          itemName = iN;
              value = value();  
    }
    
    
    
        public class Smycken extends Prylar{
         private int antalStenar;
         private boolean guldEllerSilver;
         private int value;
    
         public Smycken (Person who, String n, int aS, boolean material){
         super(who,n);
    
         antalStenar = aS;
         guldEllerSilver = material;
    }
    
    
    
    
    public Integer value() {
    
        if (guldEllerSilver){
            value = 2000;
        }
        else{
            value= 700;}
        value += (500*antalStenar);
    
        return value;
    }
    
    }

    最后,我想对大家说声谢谢,感谢你们花时间阅读并帮助一个人走出困境。我真的很感激。希望当其他人有类似的问题时,他们会偶然发现这一点


    谢谢大家

    您面临的问题是,当您从基类调用抽象(或任何重写)方法时,子类实例没有完全构造。确保对象实例完全构造的唯一方法是完成其构造函数

    解决问题的一种方法是仅将构造函数用于实例的构造,并将(动态)初始化留给方法。在这种情况下,您可以使用以下方法:

    private boolean initialized = false;
    
    public synchronized boolean init() {
        if (!initialized) {
             // allocate resources, call abstract method(s)
             initialized = true;
        }
        return initialized;
    }
    
    public synchronized void cleanup() {
        if (initialized) {
             // free resources, call abstract method(s)
             initialized = false;
        }
    }
    
    调用代码可以显式调用
    init()
    cleanup()
    方法,或者将对
    init()
    的调用保留为如下模式:

    public void doSomething() {
    
        if (init()) {
            // go!
        }
    }
    

    在init方法内部,您可以调用抽象方法,并确保正确构造完整的对象实例。

    @rsp建议的显式init()方法的另一种替代方法是延迟计算这些其他结果。e、 g

    public int getValue() {
       if (value == 0) { // some constant or value that means not-computed yet
          value = blah*foo*bar;
       }
       return value;
    }
    

    或者,对value()的计算不会花费很多时间。总是重新计算它。30年前,你会把这些东西都藏起来。缓存会创建对象为空或过时的错误。或子类。:-)处理器现在快多了,重新计算通常更简单,有时甚至更快。

    查看提交的代码示例,没有迹象表明基类中使用了抽象方法。我希望这是为了简化。否则,将该方法定义为抽象方法是没有意义的

    要在由子类计算的基类中缓存值,不应使用构造函数。在子类的构造函数有机会为其传递数据之前调用该方法,从而产生您观察到的效果

    相反,我将为抽象方法定义一个伴随方法,该方法将检查值是否已缓存,如果未缓存,则执行缓存。 考虑这个例子:

    public abstract class Base {
      private final String name;
      private BigInteger cachedValue;
    
      public Base(String name) {
        this.name = name;
      }
    
      public BigInteger calculate() {
        final BigInteger one = BigInteger.ONE;
        //do the calculation involving `value` call
        return value().multiply(one);
      }
    
      protected abstract BigInteger doComplexCalculation();
    
      protected BigInteger value () {
        if (cachedValue == null) {
            this.cachedValue = doComplexCalculation();
        }
        return this.cachedValue;
      }
    }
    
    此情况下的子类示例:

    public class SubClass extends Base {
      private int number;
    
      public SubClass(String name, int number) {
        super(name);
        this.number = number;
      }
    
      @Override
      protected BigInteger doComplexCalculation() {
        //do calculations and return a result which will be cached by the base class
        return BigInteger.valueOf(number);
      }
      //The cached value can then be accessed by other methods 
      //through the use of protected `value` method call.
    }
    

    我认为你需要发布你的代码,我可以想出2个选择-1。不要从构造函数内部调用该方法,而要在外部显式调用。2.创建另一个将捕获附加信息的抽象方法,并在抽象方法之前调用它。顺便说一句,为什么不能更改方法的签名?我不明白为什么在构造函数中调用value(),而忽略结果。我猜是打字错误,真正的代码是这样的。value=value()???是的,没错。这就是我计划使用它的方式,请参见下面我的答案。由于计算value()几乎不是火箭科学,我将完全跳过构造函数。当他们要求getValue()时,每次只需计算它。你的意思是,我没有将抽象方法放在构造函数中,而是将它放在另一个方法中-如你所建议的初始化方法?我如何检查初始化?甚至,我该如何初始化?@Dennis,是的,这就是我的意思。假设从构造函数调用抽象方法是为了初始化实例,您可以在创建新实例后直接调用init方法,或者让初始化在对对象的第一次公共调用时完成。