Comments 24
Нет, в C# это не скомпилируется.
Скомпилируется с 9.0. Ковариантные возвращаемые значения появились.
Зачем пихать всюду ООП, если можно сделать свойство вроде AvailableWeapons. Таким же образом составить карту возможных умений, которых мог бы изучить конкретный класс.
Я бы проверку на возможность носить тот или иной предмет поставил в действие "одеть оружие/применить предмет".
А ответ на то как это нужно делать далее будет где-то раскрыт? Я так понял, что тут только половина статьи или вообще ее начало...
П.С. Скажите Гендальфу, что он не может носить меч и посох одновременно)
Я бы проверку на возможность носить тот или иной предмет поставил в действие "одеть оружие/применить предмет".
У меня есть ощущение, что вы читали оригинал
А ответ на то как это нужно делать далее будет где-то раскрыт?
Конечно будет.
Я так понял, что тут только половина статьи или вообще ее начало...
Верно, только начало.
П.С. Скажите Гендальфу, что он не может носить меч и посох одновременно)
Эта шутка есть во второй части.
Нет, статью не читал, но фамилия автора где-то уже мелькала буквально сегодня. Буду ждать ваших переводов)
А что касается проверять при смене оружия - показалось самым логичным. Возможно, что геймерско-программистский опыт сказывается.
Только вот в Скайриме был замечательный баг с луком из-за этого. Унаследованный (буквально) в Fallout 4 и Starfield до каких-то поздних обновлений. Из-за того что на смену оружия было еще повешена смена экипировки, проверки амуниции и были препятствующие события, а смена оружия в итоге добавляла абилки, например, абилка "стрелять", персонаж мог застрять в состоянии "есть рот, но кричать не могу".
У Вас на лицо не верные требования из которых получается неправильная реализация.
Неверное решение, что у игрока есть оружие.
Переписав по другому всё становится намного лучше
abstract class Weapon { }
sealed class Staff : Weapon { }
sealed class Sword : Weapon { }
abstract class Player { }
sealed class Wizard : Player
{
public Staff Staff { get; set; }
}
sealed class Warrior : Player
{
public Sword Sword { get; set; }
}
Волшебник становится волшебником, так как у него есть посох.
Почему бы тогда не использовать дженерики?
abstract class Weapon { }
sealed class Staff : Weapon { }
sealed class Sword : Weapon { }
abstract class Player<T> where T: Weapon
{
public abstract T Weapon { get; set; }
}
sealed class Wizard : Player<Staff>
{
public override Staff Weapon { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
}
sealed class Warrior : Player<Sword>
{
public override Sword Weapon { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
}
Этот вариант тоже будет в следующем выпуске.
Пока ждете выпуск напишите как поместить несколько Игроков в контейнер и получить у них всех Оружие.
Понял в чем проблема с дженериками, тогда можно как-то так:
abstract class Player
{
public abstract Weapon Weapon { get; }
protected abstract void SetWeapon(Weapon weapon);
}
sealed class Wizard : Player
{
public override Weapon Weapon => throw new NotImplementedException();
public void SetWeapon(Staff weapon)
{
SetWeapon((Weapon)weapon);
}
protected override void SetWeapon(Weapon weapon)
{
throw new NotImplementedException();
}
}
У полиморфного варианта есть преимущество в том случае, если это не посох и волшебник, а объект учетной записи пользователя и какая-то привилегия (группа?), и то и другое являющееся изолированными ресурсами. На что автор намекал, говоря об "enterprise applications".
во втором случае кстати более интересна ECS подход, где волшебники и посохи перечислены отдельно, а потом связаны принадлежностями.
В чем ценность именно этого коротенького перевода, состоящего из 2 не самых удачных примеров кода? Получился бы более достойный хабра материал при склейке всех переводов в одну статью.
Воины и волшебники, часть первая