Создание неизменяемого класса

#java #immutability

#java #неизменность

Вопрос:

Я пытаюсь создать неизменяемый класс, в котором представлены натуральные числа. Я использую рекурсию для обработки методов увеличения и уменьшения. Поскольку поля являются окончательными, я создал частный конструктор для присвоения новых значений необходимым полям при уменьшении / увеличении. После тестирования этой реализации я, похоже, не могу точно указать на проблему. Если я уменьшу 100, это будет 10. Если я увеличу 99, это будет 9. Если я увеличу / уменьшу число, не находящееся на границе, я получу длинную строку тарабарщины. Я думаю, мне нужен толчок в правильном направлении. Я могу заставить его работать нормально, если он изменяемый, потому что мне не нужно беспокоиться о конечных полях.

 public final class SlowBigNatural implements BigNatural{
final private int natural[];
final private int nSize;
final private int HIGHEST = 9;

public SlowBigNatural() {
    this.nSize = 1;
    this.natural = new int[1];
    this.natural[0] = 0;
}

public SlowBigNatural(int p) {
    this(Integer.toString(p));
}

public SlowBigNatural(String s) {
    this.nSize = s.length();
    this.natural = new int[nSize];
    for (int i = 0; i < nSize; i  ) {
        this.natural[i] = Character.digit(s.charAt(i), 10);
    }
}

public SlowBigNatural(BigNatural c) {
    this(c.toString());
}

private SlowBigNatural(int[] natural, int nSize){
    this.nSize = nSize - 1;
    this.natural = new int[this.nSize];
    for (int i = 0; i < this.nSize; i  ) {
        this.natural[i] = natural[i];
    } 
}

public BigNatural increment() {
    int[] nClone = new int[nSize];
    System.arraycopy(natural, 0, nClone, 0, nSize);
    if (nSize == 1 || nClone[nSize - 1] != HIGHEST) {
        nClone[nSize - 1]  ;
        BigNatural nInc = new SlowBigNatural(nClone.toString());
        return nInc;
    } 

    else {
        nClone[nSize - 1] = 0;
        BigNatural temp = new SlowBigNatural(nClone, nSize);
        temp.increment();
        return temp;
    }
}

public BigNatural decrement() {
    int[] nClone = natural.clone();
    if (nClone[nSize - 1] != 0) {
        nClone[nSize - 1]--;
        BigNatural nDec = new SlowBigNatural(nClone.toString());
        return nDec;
    } 
    else {
        if (nSize != 1) {
            nClone[nSize - 1] = HIGHEST;
            BigNatural temp = new SlowBigNatural(nClone, nSize);
            temp.decrement();
            return temp;
        }
        else{
            BigNatural nDec = new SlowBigNatural(0);
            return nDec;
        }
    }
}

public String toString() {
    String nString = "";
    for (int i = 0; i < nSize; i  ) {
        nString  = String.valueOf(natural[i]);
    }
    return nString.replaceFirst("^0 (?!$)", "");
}
}
  

Я прошелся по своему коду, и, похоже, ошибка возникает, когда я преобразую массив в строку и передаю его через конструктор. Это превращает массив в кучу безумия. Продолжаем расследование.

Комментарии:

1. Ваш код не имеет большого смысла. Например, почему в этом утверждении — if (nSize == 1 || nClone[nSize - 1] != HIGHEST) — вы проверяете nSize == 1?? И почему на следующем этапе else вы делаете temp.increment() , а затем возвращаете temp, а не возвращаете результат temp.increment() , если ваш класс предположительно неизменяем??

Ответ №1:

Не полностью изучил это, но если SlowBigNatural действительно правильно неизменен, то следующее:

 BigNatural temp = new SlowBigNatural(nClone, nSize);
temp.increment();
return temp;
  

насколько я могу судить, вряд ли это будет полезно. Приведенный выше вызов temp.increment() создает новый объект, который вы игнорируете, поскольку видно, что вы возвращаете сам temp, а не результат temp.increment() .

Не могли бы вы попробовать изменить приведенное выше на это:

 BigNatural temp = new SlowBigNatural(nClone, nSize);
return temp.increment();
  

И если работает, сделайте то же самое для decrement() .

Комментарии:

1. Я попробовал ваше предложение, и теперь я получаю случайную тарабарщину, когда устанавливаю новое значение, равное увеличенному значению. В настоящее время я пытаюсь просмотреть код, чтобы увидеть, где именно я ошибаюсь.