2014-12-31 3 views
1

Я не совсем уверен, как задать этот вопрос, не публикуя здесь весь код (это совсем немного), но я постараюсь изо всех сил.Почему этот метод не рекурсивный?

У меня есть класс enum, который реализует интерфейс. Цель всей программы - представить кучу целочисленных чисел в полях. Таким образом, существует конкретный класс TrueField, который получен из абстрактного класса AbstractField, который реализует метод, называемый boolean sameAs(Field that). Этот метод также существует (он должен, из-интерфейса) в классе перечислимом:

enum SimpleField implements Field{ 

    Empty(),Zero(0),Binary(0,1),Unsigned(Integer.MAX_VALUE); 

    private Field simpleField; 

    SimpleField(int... intArray){ 
     simpleField = new TrueField(intArray); 
    } 

    @Override 
    public boolean sameAs(Field that){ 
     return that.sameAs(simpleField); 
    } 
} 

Реализация от TrueField:

public class TrueField extends AbstractField{ 

private final int[] intArray; 

TrueField(int... thatArray){ 
    intArray = thatArray; 
} 

@Override 
public int at(int index){ 
    if(index<0 || index>=intArray.length){ 
     throw new IndexOutOfBoundsException(); 
    } 

    return intArray[index]; 
} 

@Override 
public int length(){ 
    return intArray.length; 
} 
... 

AbstractField:

public abstract class AbstractField implements Field{ 

@Override 
public abstract int length(); 


@Override 
public boolean sameAs(Field that){ 
    if(that==null) 
     throw new RuntimeException("that is null"); 

    boolean result = true; 

    if(length()==that.length()){ 
     for(int i=0;i<length();i++){ 
      if(at(i)!=that.at(i)) 
       result = false; 
     } 
    } 
    else 
     result = false; 

    return result; 
} 

@Override 
public String toString(){ 

    String result = ""; 

    for(int i=0;i<length();i++){ 
     result += at(i); 

     if(length()-i>1) 
      result += ","; 
    } 

    return "["+result+"]"; 
} 

}

Мой вопрос: когда я делаю что-то подобное в моем основном методе:

Field sf = SimpleField.Binary; 
Field sf2 = SimpleField.Binary; 
Field tf = new TrueField(1,2); 

System.out.println(sf.sameAs(sf2)); 

... очевидно, метод sameAs в классе перечислений называется. Но почему он снова не называет себя рекурсивным? Поскольку существует динамическое связывание из-за интерфейса, JVM видит, что sf является динамическим типом SimpleField.Binary и статическим типом Field. Я не совсем понимаю, что происходит, и почему он снова не называет себя. Надеюсь, я достаточно подробно объяснил свой вопрос.

+2

Зачем ему снова называть себя? Он вызывает метод с именем 'sameAs' на объекте, на который ссылается' this' (если только 'this' не ссылается на тот же объект, что и' this'). –

+1

Есть две реализации, но вы только показали нам одну из них.Было бы очень полезно, если бы вы показали * обе * реализации - в идеале короткую, но полную программу, демонстрирующую проблему. –

+0

Вау, что было быстро, спасибо. @JonSkeet – kimsay

ответ

0

Это не рекурсивный, потому что ваш метод sameAs в SimpleField перечислении вызывает sameAs метод объекта параметра, который неSimpleField, это TrueField.

Таким образом, метод sameAs запускается, как указано в классе Field.

При дальнейшем рассмотрении, может быть рекурсивным, но только если декларация в TrueField классе была рекурсивными также, , который мы можем видеть, что это не так, теперь, когда этот код был добавлен выше.

+0

Я просто понял, что я действительно хотел сделать обратное, пожалуйста, посмотрите на отредактированный код в основном методе. @ mbomb007 – kimsay

+0

@kimsay Спасибо, что разместили этот код. Теперь, когда мы видим это, мы знаем, что он не рекурсивный. Он вызывает метод, содержащийся в другом объекте, который сравнивает эти два и возвращает логический результат. – mbomb007

0

Метод не рекурсивный, потому что он не звонит сам.

@Override 
public boolean sameAs(Field that){ 
    return that.sameAs(simpleField); 
} 

Этот метод использует аргумент для вызова sameAs. Аргумент вполне может быть одним и тем же перечислением, но он все еще не называет себя.

Это пример простого рекурсивного метода:

public long factorial(int value) { 
    return value == 0 ? 1 : factorial(value-1); 
} 

В этом нет никакой дополнительной ссылки использовать для вызова метода снова; Я просто вызываю его еще раз с небольшим изменением параметров.

+0

спасибо, что вы до сих пор ребята. @ Макото, не могли бы вы рассказать мне, что происходит ровно шаг за шагом, когда он называется. Я как-то теряю forrest для деревьев :( – kimsay

Смежные вопросы