Как вынудить производный класс включать определенные свойства со значением по умолчанию

У меня есть структура класса для ролевой игры играющего, которая похожа на это...

public abstract class Item
{
   public abstract string Name { get; set; }
}

public abstract class Armor : Item
{
   public override string Name { get; set; }
}

public class Helmet : Armor
{
   public override string Name { get; set; }
}

В основном я пытаюсь вынудить каждый производный тип включать свойство "Name". Действительно ли это - лучший способ сделать это? Я знаю, что могу удалить "краткий обзор" из Объекта. Назовите и затем удалите переопределенные свойства "Name" в Броне и Шлеме. Если я делаю это, код выглядит немного более чистым, но я мог бы забыть устанавливать основу. Имя в этих производных классах.

Мог кто-то помогать показать мне лучший способ сделать это?

Править: Извините, позвольте мне разъяснить свой вопрос немного больше. Я хочу удостовериться в 2 вещах. 1) свойство Name существует во всех производных классах 2), свойство Name не является пустым или пустым

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

8
задан mikedev 28 January 2010 в 21:33
поделиться

7 ответов

Похоже, вы беспокоитесь об инициализации свойств?

Но я мог бы забыть установить Base.name В этих полученных классах.

Один из способов вы можете заставить свой свой свой свой свой свой свой состоит в том, чтобы включить этот улавчик в вашем конструкторе базового класса, как так:

public class MyBaseClass
{
    private string _name;

    public MyBaseClass(string name)
    {
        _name = name;
    }
}

, то все, что происходит от MyBaSeClass, должно удовлетворять этот конструктор:

public class MyDerivedClass
{
    public MyDerivedClass(string name) : base(name)
    {

    }
}

, тогда вы также можете сделать Собственность либо:

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

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

Другой подход, как показывает другие ответы, заключается в реализации виртуальной собственности, которая бросает исключение в ее базовой реализации.

9
ответ дан 5 December 2019 в 10:02
поделиться

Если я сделаю это, код выглядит немного очистителем, но я мог бы забыть установить базу. Войти в эти полученные классы.

Тогда название объекта просто будет иметь что-то глупости.

Лучше еще, у имя начинается как NULL . Затем вы получите исключение, если вы забудете инициализировать имя, но кто-то пытается использовать его, и вы узнаете, что вы должны его исправить.

-121--3594981-

будет делать имени виртуальным т. Е. Общественное виртуальное имя {get; набор; } Accessor использоваться в классе элементов? Поскольку людьми и броня спускаются от класса товара. Это приведет к тому, что они должны быть переопределены ...

Надеюсь, это поможет, С уважением, Том.

0
ответ дан 5 December 2019 в 10:02
поделиться

Майк правильно, что если вы просто хотите использовать свойство «имя» на всех производных объектах, вам не нужно, чтобы он был отмечен абстрактным, как это унаследовано.

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

Взгляните на этот код:

public class Item
{
   public string Name { get; set; }

   public Item(string name)
   {
       this.Name = name;
   }

   protected Item() {}
}

public class Armor : Item
{   
   public Armor(string name) : base(name) {}
   protected Armor() {}
}

public class Helmet : Armor
{   
   public Helmet(string name) : base(name) {}
   protected Helmet() {}
}

Вышеуказанные определения означают, что:

Helmet myHelmet = new Helmet(); //will not build
Helmet myHelmet = new Helmet("Some Fancy Helmet Name"); //will build

Armor myArmor  = new Armor (); //will not build
Armor myArmor  = new Armor ("Some Fancy Armor Name"); //will build

Item myItem = new Item (); //will not build
Item myItem = new Item("Some Fancy Item Name"); //will build

Это усиливает, что любой экземпляр классов должен определять имя во время создания. Одно возможное решение в любом случае ...

2
ответ дан 5 December 2019 в 10:02
поделиться
[1141396-

Так что это зависит от того, что вы хотите сделать ...

Создание аннотации класса выполняет все подкласс для реализации класса (и его абстрактных функций и т. Д.), Но если вы Хотите функцию иметь функцию базовой функциональности с возможностью переопределить функцию, то я предложу не сделать аннотацию класса и вместо этого сделать конкретную функцию виртуальной, таким образом, когда виртуальная функция не перезаписывается, а базовая функция будет вызываться.

И всегда есть варианты создания «новых» свойств с тем же именем, но я не думаю, что это хорошая практика.

Надеюсь, что поможет.

0
ответ дан 5 December 2019 в 10:02
поделиться

Если я сделаю, код выглядит немного очистителем, но я могу забыть установить базу. Немейте в этих полученных классах.

Тогда имя объекта просто будет окажется что-то глупо.

Лучше еще, у имя начинается как NULL . Затем вы получите исключение, если вы забудете инициализировать имя, но кто-то пытается использовать его, и вы узнаете, что вы должны его исправить.

2
ответ дан 5 December 2019 в 10:02
поделиться

MySQL не имеет какой-либо функции анализа/ранжирования, но вы можете использовать переменную для искусственного создания значения ранга:

  SELECT t.id,
         t.udid,
         t.name,
         t.score,
         @rownum := @rownum + 1 AS rank
    FROM HIGHSCORES t
    JOIN (SELECT @rownum := 0) r
ORDER BY t.score DESC

Чтобы увидеть, какой ранг связан с UDID «0000», используйте:

SELECT MAX(x.rank) AS rank
  FROM (SELECT t.id,
               t.udid,
               t.name,
               t.score,
               @rownum := @rownum + 1 AS rank
          FROM HIGHSCORES t
          JOIN (SELECT @rownum := 0) r
      ORDER BY t.score DESC) x
 WHERE x.udid = '0000'

Требуется MAX , если у пользователя есть несколько высоких значений баллов. Кроме того, нельзя использовать MAX и ORDER BY rank LIMIT 1 .

-121--4859672-

В C # тип int безопасен для потоков.

Так как вы сказали, что только один поток записывает в него, вы никогда не должны спорить о том, что является правильным значением, и, пока вы кэшируете локальную копию, вы никогда не должны получить грязные данные.

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

Также помните, что некоторые операции не являются атомарными и могут вызвать проблемы при наличии нескольких устройств записи. Например, несмотря на то, что тип bool не повреждается при наличии нескольких устройств записи, оператор, подобный

a = !a;

, не является атомарным. Если одновременно считываются два потока, возникает условие гонки.

-121--2970322-

Необходимо только определить Name в базовом классе и не указывать его как абстрактный. Он по-прежнему будет доступен как свойство во всех производных классах.

public abstract class Item
{
   public string Name { get; set; }
}

public abstract class Armor : Item
{ }

public class Helmet : Armor
{ }
4
ответ дан 5 December 2019 в 10:02
поделиться

I Думаю, вы все еще можете сделать свойство виртуальной в абстрактном классе, поэтому следует решить вашу проблему.

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

public abstract class Item
{
   public virtual string Name 
   { 
         get {return m_strName;} 
         set {m_strName = value;}
   }

public abstract class Armor : Item
{
   public override string Name { get; set; } // if you want to override it 
}

public class Helmet : Armor
{
   public override string Name { get; set; } // if you want to override it
}
0
ответ дан 5 December 2019 в 10:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: