Изменить поле каждый раз, когда изменяется другое поле

2

Ну, название говорит об этом, но я буду более конкретным в своей ситуации и объясню свою проблему. У меня есть следующие классы:

class Attribute{
    private int score;
    private int tempScore;
    private int misc;

    // here I have getters and setters
    // A method
    public int Modifier(){
        return (score+tempScore-10)/2;
    }
}

а также

class SavingThrow{
    private int base;
    private int resistance;
    private int bonus;
    private int misc;

    //Getters and setters here
    //A method
    public int Total(){
        return base + resistance + bonus + misc;
    }
}

Скажем, теперь у меня есть игрок А с мудростью Атрибута и SavingThrow. Всякий раз, когда изменяется первый, например:

A.Wisdom.Score = 12;

то второе должно быть изменено как следствие. В этом примере я должен сделать:

A.Will.Bonus = A.Wisdom.Modifier();

Любая идея о том, как достичь этого?

Я подумал о следующем решении, но это не удовлетворяет меня по той причине, которую я собираюсь объяснить.
Я не буду определять геттеры, поэтому внешний доступ к Мудрости может быть выполнен только с помощью предопределенного публичного метода, например SetWisdom (int score), и в этом методе я обновляю Will. Хотя проблема заключается в том, что если мне нужно изменить tempScore или misc вместо этого, я должен сделать другой метод для этого. Это кажется довольно неэффективным, особенно если я добавлю дополнительные поля в класс атрибутов.
Кроме того, я мог бы использовать метод SetWisdom (атрибут мудрости), который заменяет весь атрибут новым объектом, в котором я должен скопировать ВСЕ немодифицированные поля и заменить тот, который мне нужен. Это кажется немного неуклюжим и нелепым. Какое решение вы бы выбрали и, что более важно, у вас есть лучшие идеи о том, как справиться с этим?

  • 4
    base - это ключевое слово в C #, его нельзя использовать как имя переменной.
  • 2
    Я думаю, что вы ищете INotifyPropertyChanged . Ваши поля должны будут поменяться на свойства, и пока вы там, вы можете также изменить свои методы Total и Modifier на свойства только для чтения, чтобы соответствовать стандартному использованию .NET.
Показать ещё 4 комментария
Теги:
field

1 ответ

3
Лучший ответ

Самый простой вариант - не делать копии значения вообще, тогда вам не нужно отслеживать, где вы его скопировали, чтобы обновить его.

class SavingThrow{
    private int base;
    private int resistance;
    private Attribute attribute;
    private int misc;

    //Getters and setters here
    //A method
    public int Total(){
        return base + resistance + attribute.Modifier + misc;
    }
}

Ваш класс может использоваться таким образом, если вы установите атрибут в конструкторе:

Attribute wisdom = new Attribute(16);
SavingThrow will = new SavingThrow(wisdom);

Console.WriteLine(will.Total());

wisdom.Add(2);

Console.WriteLine(will.Total());

Общий балл должен был увеличиться (при условии, что добавление двух к мудрости увеличивает модификатор), потому что класс спасброска никогда не содержал копию, но напрямую ссылался на мудрость.

  • 0
    Очень понятное и приятное решение. Я попробую это! Большое спасибо!
  • 0
    У меня та же проблема, но с целым числом. У игрока есть поле size а у ArmorClass есть поле size . Тем не менее, я вынужден скопировать его сейчас, потому что это не объект, а примитив (также я не могу оставить поле только в ArmorClass, потому что он нужен мне в Player для других классов). Должен ли я использовать указатель? Хотя это unsafe территория, поэтому я не уверен, что это правильное решение. Или я должен просто упаковать это в классе и использовать это?
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню