Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.78/41: Рейтинг темы: голосов - 41, средняя оценка - 4.78
 Аватар для skilllab
296 / 236 / 58
Регистрация: 03.02.2011
Сообщений: 2,051
Записей в блоге: 1
.NET 4.x

Классы или интерфейсы?

10.06.2017, 23:28. Показов 9522. Ответов 129
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Согласно новомодным книжкам от очередных гуру программистов, делаю на уровне интерфейсов.
Итак, накидаю примерчик:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public interface IRowViewModel : INotifyPropertyChanged
{
   ISomeItem Item {get;set;}
   string Designation { get;}
   string Name { get;}
}
 
public interface IMaterialRow : IRowViewModel
{
   double Thickness { get; }
}
 
public class SpecMaterialRow : PropertyChangedBase, IMaterialRow
{
   public ISomeItem Item { get; }
   public SpecMaterialRow(ISomeItem _item)
   {
      Item = _item;
   }
 
   public string Designation
   {
      get { return Item.Designation; }
      set { Item.Designation = value;}
   }
   
   public string Name
   {
      get { return Item.Name; }
      set { Item.Name= value;}
   }
   
   public double Thickness => Item.Thickness ;
}
Далее в коде гденить кастую и беру значение свойства.

Уно:
C#
1
2
3
4
if (rowViewModel is SpecMaterialRow )
  {
      string tempVar = ((SpecMaterialRow) rowViewModel ).Designation;
  }
Дос:
C#
1
2
3
4
if (rowViewModel is IMaterialRow  )
  {
      string tempVar = ((IMaterialRow) rowViewModel ).Designation;
  }
Вопрос: какая конструкция тогда вообще будет более корректна или верна?
1
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
10.06.2017, 23:28
Ответы с готовыми решениями:

Как правильно разработать архитектуру программы (классы, интерфейсы)
Здраствуйте, минут двадцать пытаюсь сформулировать вопрос, то напишу то удалю :D, вообщем вопрос с чего начать разработку программы по...

Абстрактный класс, интерфейсы или простые классы с иерархией ?
Понять кое-что из ОПП 1-й Вопрос: Есть описание абстрактного класса abstract class HeroFactory { public abstract Movement...

Интерфейсы. Выделить у классов общий интерфейс(или интерфейсы)
Задание: У классов выделить общий интерфейс ( или интерфейсы ). первый класс : using System; using...

129
 Аватар для skilllab
296 / 236 / 58
Регистрация: 03.02.2011
Сообщений: 2,051
Записей в блоге: 1
11.06.2017, 11:52  [ТС]
Студворк — интернет-сервис помощи студентам
"свойство с признаком" - ну и зачем мне тогда вообще классы? Один "god" класс со ста свойствами и 2 мя методами)) получается.
"можно использовать AS\IS" - то есть кастование это зло?))

Добавлено через 2 минуты
Можете, пожалуйста, уточнить, почему is (или без is, просто direct cast) на интерфейс - это плохо?

Добавлено через 2 минуты
Ну, тоесть "уно" пример это хорошо, а "дос" между плохо и иногда_надо
0
Эксперт .NET
 Аватар для Usaga
14783 / 9557 / 1366
Регистрация: 21.01.2016
Сообщений: 36,033
11.06.2017, 12:21
Цитата Сообщение от skilllab Посмотреть сообщение
"свойство с признаком" - ну и зачем мне тогда вообще классы?
Нелогичный вывод вы сделали.

Цитата Сообщение от skilllab Посмотреть сообщение
то есть кастование это зло?))
Нет, если ограниченно и с умом используется.

Цитата Сообщение от skilllab Посмотреть сообщение
Можете, пожалуйста, уточнить, почему is (или без is, просто direct cast) на интерфейс - это плохо?
Потому, что делает интерфейс бесполезным. У вас есть абстракция, которая не абстракция.

Кстати, оба примера так себе. Производительнее было бы сделать так:
C#
1
2
3
4
IMaterialRow  materialRow = rowViewModel as IMaterialRow ;
if (materialRow != null) {
    // делаем дела
}
Так программе только один раз нужно в метаданные лезть, а не два, как в обоих ваших примерах.

Добавлено через 3 минуты
Ещё одно кстати: если у вас 5 разных типов за интерфейсом скрыто, и вам над всеми типами нужно сотворить работу (сделать цепочку вызовов if (a is b)), то это ещё и не производительно будет. А вот если использовать double dispatch, то определить тип алгоримта, что нужно выполнить над записью, можно будет строго в один вызов метода, что быстрее и правильнее.
0
 Аватар для skilllab
296 / 236 / 58
Регистрация: 03.02.2011
Сообщений: 2,051
Записей в блоге: 1
11.06.2017, 12:29  [ТС]
Что такое double dispatch?
0
Эксперт .NET
 Аватар для Usaga
14783 / 9557 / 1366
Регистрация: 21.01.2016
Сообщений: 36,033
11.06.2017, 12:39
skilllab, можно же погуглить))

Добавлено через 7 минут
Вот простой пример:

Кликните здесь для просмотра всего текста

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
using System;
using System.Collections.Generic;
 
namespace OtherConsoleExperiments
{
    interface ISomeShitPrinter
    {
        void PrintFirstShit(FirstShit shit);
        void PrintSecondShit(SecondShit shit);
    }
 
    interface ISomeShit
    {
        void Accept(ISomeShitPrinter printer);
    }
 
    class FirstShit : ISomeShit
    {
        public string FirstShitParam { get; set; }
 
        public void Accept(ISomeShitPrinter printer)
        {
            printer.PrintFirstShit(this);
        }
    }
 
    class SecondShit : ISomeShit
    {
        public string SecondShitParam { get; set; }
        public void Accept(ISomeShitPrinter printer)
        {
            printer.PrintSecondShit(this);
        }
    }
 
    class ShitPrinter : ISomeShitPrinter
    {
        public void PrintFirstShit(FirstShit shit)
        {
            Console.WriteLine(shit.FirstShitParam);
        }
 
        public void PrintSecondShit(SecondShit shit)
        {
            Console.WriteLine(shit.SecondShitParam);
        }
    }
 
    class Program
    {
        static void PrintShit(IEnumerable<ISomeShit> shitList)
        {
            var printer = new ShitPrinter();
 
            foreach (var item in shitList)
            {
                item.Accept(printer);
            }
        }
 
        static void Main(string[] args)
        {
            List<ISomeShit> shitList = new List<ISomeShit>
            {
                new FirstShit{ FirstShitParam = "blah" },
                new SecondShit{ SecondShitParam = "blah2" },
            };
 
            PrintShit(shitList);
 
            Console.ReadKey();
        }
    }
}
1
 Аватар для skilllab
296 / 236 / 58
Регистрация: 03.02.2011
Сообщений: 2,051
Записей в блоге: 1
11.06.2017, 13:03  [ТС]
Ясно. Нет, над всеми объектами мне не надо делать что то.
". У вас есть абстракция, которая не абстракция." класс получил свойства, которые есть в базовом интерфейсе и интерфейсе наследнике. Кастом я определяю принадлежность любого класса с базовым интерфейсом его принадлежность наследникам. Что не так?
Почему вообще не уйти от интерфейса и делать классами, я вроде ранее написал.
0
Эксперт .NET
 Аватар для Usaga
14783 / 9557 / 1366
Регистрация: 21.01.2016
Сообщений: 36,033
11.06.2017, 13:05
skilllab, я уже писал, что не так. Фиг с ним, я притомился уже объяснять. Работает и ладно.
0
Эксперт .NETАвтор FAQ
 Аватар для Storm23
10428 / 5158 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
11.06.2017, 15:03
skilllab, Судя по описанию вашей задачи, вам может помочь компонентная модель (суть которой в том, что объект представляет собой контейнер, содержащий набор компонентов).
Что же касается конкретно вашего вопроса, то
1) Вариант if (rowViewModel is SpecMaterialRow ) точно неправильный, потому что смысл интерфейса полностью теряется если проверять на конкретный тип. С таким же успехом можно в методы просто object передавать без всяких интерфейсов. И тоже кастить их к SpecMaterialRow.
2) Ну и если брать конкретно ваш пример, то вообще непонятно зачем там делать приведение, ведь свойство Designation доступно еще на уровне IRowViewModel. То есть приводить ничего не нужно. Возможно у вас просто неудачный пример.
1
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
11.06.2017, 16:28
skilllab, действительно, не совсем понятен сам смысл введения интерфейса, раз вам так или иначе приходится по ходу выполнения приводить его к тому или иному типу.
Я не гуру программирования, и хоть и читал про паттерны разных авторов, но думаю, что в первую очередь нужен здравый смысл. В абстракцию выводится все общее, чтобы за ней скрыть детали и работать с типом абстракции, не зна реальный тип объекта.
Вот, на мой взгляд, классический пример. Тут даже две абстракции, и мы работаем на их уровне, совершенно не зная, чем они являются на самом деле и как работают внутри.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace ConsoleApplication1 {
    class Program {
        static void Main(string[] args) {
            ModelCreator creator = ModelCreatorFactory.GetCreator("one");
            IRowViewModel[] models = creator.CreateModels();
            foreach (IRowViewModel model in models) {
                Console.WriteLine(model.Description);
            }
            Console.ReadLine();
        }
    }
 
    static class ModelCreatorFactory {
        public static ModelCreator GetCreator(string arg) {
            ModelCreator creator = null;
            switch (arg) {
                case "one":
                    creator = new OneModelCreator();
                    break;
                case "two":
                    creator = new TwoModelCreator();
                    break;
                default:
                    throw new ArgumentException("Wrong argument");
            }
            return creator;
        }
    }
 
    abstract class ModelCreator {
        public abstract IRowViewModel[] CreateModels();
    }
    class OneModelCreator : ModelCreator {
        public override IRowViewModel[] CreateModels() {
            return new IRowViewModel[]{
                new OneRowViewModel()
            };
        }
    }
    class TwoModelCreator : ModelCreator {
        public override IRowViewModel[] CreateModels() {
            return new IRowViewModel[]{
                new TwoRowViewModel()
            };
        }
    }
 
    interface IRowViewModel {
        string Description { get; }
    }
    class OneRowViewModel : IRowViewModel {
        public string Description {
            get { return "ONE"; }
        }
    }
    class TwoRowViewModel : IRowViewModel {
        public string Description {
            get { return "TWO"; }
        }
    }
}
1
 Аватар для skilllab
296 / 236 / 58
Регистрация: 03.02.2011
Сообщений: 2,051
Записей в блоге: 1
11.06.2017, 19:01  [ТС]
Цитата Сообщение от insite2012 Посмотреть сообщение
раз вам так или иначе приходится по ходу выполнения приводить его к тому или иному типу
Я ж написал, один заокеанский программист такое как-то посоветовал (не индус )
Теперь не "в двух словах"
Кликните здесь для просмотра всего текста

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
public class SpecRowViewModel : INotifyPropertyChanged
  {
     public virtual double Count { get; set; }
     public virtual double DeepCount { get; set; }
     public virtual string Designation { get; set; }
     public ISpecificationItem Item { get; set; }
     public virtual string Name { get; set; }
     public int Position { get; set; }
 
     public SpecRowViewModel(ISpecificationItem item)
       {
           Item = item;
       }
  }
    
public class SpecPartRow : SpecRowViewModel
  {
 
     public SpecPartRow(ISpecificationItem item) : base(item)
       {
       // подписка на изменения событий как конкретно текущих свойств, так и наследников
       }
 
     public override double Count
     {
         get { return !Item.IsDeep ? Item.ModelCount : 0; }
         set { Item.ModelCount = value; }
     }
     
     public override double DeepCount => Item.DeepCount;
 
     public override string Designation
       {
          get { return Item.Designation; }
          set { Item.Designation = value; }
       }
 
      public override string Name
      {
         get { return Item.Name; }
         set { Item.Name = value; }
      }
  }
 
public class SpecMaterialRow : SpecRowViewModel
  {
     public MaterialPanelData MaterialPanelData { get; set; }
    
     public SpecPartRow(ISpecificationItem item) : base(item)
       {
    //для примера
    MaterialPanelData = Item.MaterialPanelData;
    MaterialPanelData += OnPropChanged;
    //....
        }
     
      public double Count
      {
         get
            {
                if (Item is MaterialSpecification)
                {
                    return (Item as MaterialSpecification).ModelCount;
                }
                if (Item is PartSpecification)
                {
                    return (Item as PartSpecification).MaterialCount;
                }
                if (Item is AssemblySpecification)
                {
                    return (Item as AssemblySpecification).MaterialCount;
                }
                return 0;
            } set { throw new System.NotImplementedException("Не реализовано в " + nameof(SpecMaterialRow)); }
        }
    
       public double DeepCount
         {
            get
            {
                if (Item.Type == EDocumentSection.Parts)
                {
                    return (Item as PartSpecification).DeepMaterialCount;
                }
                if (Item.Type == EDocumentSection.Assemblies)
                {
                    return (Item as AssemblySpecification).DeepMaterialCount;
                }
                if (Item.Type == EDocumentSection.Materials)
                {
                    return (Item as MaterialSpecification).DeepCount;
                }
                return -999;
            }
        }
        
        public string Designation
        {
            get { return RowType == ERowType.IsPart ? MaterialPanelData.MaterialDesignationInBase : Item.Designation; }
 
            set
            {
                if (RowType == ERowType.IsPart)
                {
                    MaterialPanelData.MaterialDesignationInBase = value;
                }
                Item.Designation = value;
            }
        }
 
        public string Name
        {
            get { return RowType == ERowType.IsPart ? MaterialPanelData.MaterialNameInBase : Item.Name; }
 
            set
            {
                if (RowType == ERowType.IsPart)
                {
                    MaterialPanelData.MaterialNameInBase = value;
                }
                Item.Name = value;
            }
        }
}
Есть так же "пустые классы", у которых заполнено только свойство Name (SpecHeaderRow), это имена разделов. Есть просто пустые классы, это разделения строк (SpecEmptyRow). Есть даже классы, которые предназначены для объединения одинаковых классов (классы, у которых совпадает Name и Designation) в один. В классе присутствует помимо основных свойств ещё и List<SpecRowViewModel>.
Есть List<SpecRowViewModel> со всеми этими классами. Лист предназначен для отображения на Datagrid WPF (там всякие конвертеры, )
Соответственно везде по коду встречается такое:
C#
1
2
3
4
5
6
7
8
if (rowViewModel is SpecHeaderRow || rowViewModel is SpecEmptyRow)
                    continue;
                if (rowViewModel is SpecDocumentRow)
                    continue;
                if (rowViewModel is SpecMaterialRow)
                    continue;
                if (rowViewModel is SpecPaintRow)
                    continue;
C#
1
2
3
4
5
6
7
8
9
10
if (rowViewModel is SpecStandartRow)
                {
                    if (rowViewModel.Item.From != EFrom.Part && !rowViewModel.Item.IsDeep)
                    {
                        rowViewModel.Position = i;
                        i++;
                    }
                        continue;
                    
                }
Так вот, так как делается всё это давно, и много чего надо уследить, да и свойства добавляются но не в базовый класс а в наследников, то встречается неоднозначность. К примеру ввёл свойство SummCount в наследника. Чот нахимичил спустя пару месяцев, а потом понял что оно должно возвращать то же что и Count. Интерфейс в данном случае был бы как "скелет"
всех свойств, которые ОБЯЗАТЕЛЬНО должны быть в базовой поставке)) + ОБЯЗАТЕЛЬНО должны быть определённые,
характерные для наследников. Т.е. интерфейс - это прототип. После введения интерфейса я ТОЧНО теперь знаю какие свойства где должны быть. Каждый класс ТОЧНО их реализовал. С виртуальными я периодически забывал их override-ить, и где то лепил new


Добавлено через 3 минуты
Т.е. применение интерфейса не по назначению ))) а типа как в С++ (там вроде обязательно должны быть прототипы классов перед их использованием)
0
215 / 149 / 48
Регистрация: 28.12.2016
Сообщений: 716
11.06.2017, 19:20
skilllab, на костер его!
Шайтан!!!
0
 Аватар для skilllab
296 / 236 / 58
Регистрация: 03.02.2011
Сообщений: 2,051
Записей в блоге: 1
11.06.2017, 20:13  [ТС]
Цитата Сообщение от Defences Посмотреть сообщение
на костер его!
ну может он тоже плохо понял что я ему объяснял и чего хотел добиться в самом начале пути. Хотя, вот это кастование к интерфейсу меня тож смутило. Собственно, он предлагал то что я написал в самом начале темы, но вот с каким смыслом: есть основной интерфейс IMainInterface. Есть классы, которые имплементируют этот основной интерфейс, а есть классы, в которых нужно заложить доп свойства. Так вот прототипом для этих классов был бы основной интерфейс плюс IHasMaterial к примеру, или IHasPaint Что означало бы что у некоего класса Деталь (доска) имела свойства материала или была покрашена. А вот к примеру другая Стандартная_Деталь (типа винт) имела бы материал но её НЕЛЬЗЯ было бы покрасить.
Ключевое тут IHas...

Добавлено через 7 минут
Цитата Сообщение от Storm23 Посмотреть сообщение
компонентная модель
загуглил. Интересная вещь. Ко мне не подходит. У меня чётко всё уже определено. Каждый класс имеет свой набор и не больше. Именно в моём случае проще расширить класс одним свойством чем добавлять компонент. Т.е. идея применима, но это просто ВСЁ надо переписывать. Да и местами будут чуток костыли)))

Добавлено через 1 минуту
Цитата Сообщение от Storm23 Посмотреть сообщение
просто неудачный пример
да, пример был "на коленке". Ибо кастованием добивался того, что именно в ТОМ классе есть именно ТО свойство, которого нет ни в базовом ни в других.

Добавлено через 10 минут
Во, нашёл тот код. Заокеанский предлагал вот это:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public interface IHasMaterial
 {
    MaterialPanelData MaterialPanelData { get; set; }
 }
 
ObservableCollection<ISpecificationItem> items = ....
 
List<SpecRowViewModel> rows = new List<SpecRowViewModel>();
 
rows.Add(new SpecHeaderRowViewModel("Расходные материалы"));
 
rows.AddRange(items.Where(
                  x => x is IHasMaterial && (x as IHasMaterial).MaterialPanelData != null)
                  .Select(x => new RefMaterialRow(x as IHasMaterial)));
0
Master of Orion
Эксперт .NET
 Аватар для Psilon
6102 / 4958 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
12.06.2017, 02:15
skilllab, если у вас фиксированный набор операций, но разное поведение, это решается обычным ООП. Есть круг и квадарт, которые реализуют IEntityWithArea, понадобился треугольник: отнаследовались и реализовали этот интерфейс. ЧТобы посчитать площадь в квадрате мы просто можем написать функцию GetArea(IEntityWithArea entity) => Math.Pow(entity.Area, 2); - обычное ООП. Если у нас есть фиксированный набор объектов, но разный набор операций, например у нас есть только квадраты и треугольники, но мы хотим и площадь посчитать, и размер, и объем, и все-все-все, тогда стандартный подход - визиторы. Собсна тут про это.

И в том, и в другом случае проверка на тип через as и is выглядит странно. Почти всегда это запах и подпорки. В коде встречаются, но стремиться к ним не стоит.

В последнем примере выглядит относительно адекватно, мы выбираем сущности определенного типа, хотя я бы писал что-то вроде:
C#
1
2
3
rows.AddRange(items.OfType<IHasMaterial>
                   .Where(x => x.MaterialPanelData != null)
                   .Select(x => new RefMaterialRow(x)));
1
 Аватар для skilllab
296 / 236 / 58
Регистрация: 03.02.2011
Сообщений: 2,051
Записей в блоге: 1
12.06.2017, 10:57  [ТС]
Цитата Сообщение от Psilon Посмотреть сообщение
Почти всегда это запах и подпорки
ну так если имеем List<Figures> с Triangle, Circle, Square, Shape, и нужно пробежаться по листу по порядку и для каждого типа совершить получение свойства (или задание свойства) из класса (а свойство уникально для каждого класса), то и получится is и as же

Добавлено через 5 минут
Цитата Сообщение от Psilon Посмотреть сообщение
тогда стандартный подход - визиторы
Да нет у меня в классах методов))) нет. Одни свойства.
И НАД классами я никакой работы делать не буду. А только С классами (то бишь изменять свойства конкретного класса)

Добавлено через 9 минут
Цитата Сообщение от Psilon Посмотреть сообщение
проверка на тип
Цитата Сообщение от Psilon Посмотреть сообщение
items.OfType

Что typeOf() что is ...

Добавлено через 6 минут
И ещё чуток.
Цитата Сообщение от Usaga Посмотреть сообщение
Потому, что делает интерфейс бесполезным. У вас есть абстракция, которая не абстракция.
Цитата Сообщение от skilllab Посмотреть сообщение
public interface IHasMaterial
*{
* * MaterialPanelData MaterialPanelData { get; set; }
*}
Цитата Сообщение от Psilon Посмотреть сообщение
В последнем примере выглядит относительно адекватно
0
Эксперт .NET
 Аватар для Usaga
14783 / 9557 / 1366
Регистрация: 21.01.2016
Сообщений: 36,033
12.06.2017, 12:39
Цитата Сообщение от skilllab Посмотреть сообщение
ну так если имеем List<Figures> с Triangle, Circle, Square, Shape, и нужно пробежаться по листу по порядку и для каждого типа совершить получение свойства (или задание свойства) из класса (а свойство уникально для каждого класса), то и получится is и as же
Как-то это очень спорно выглядит, если честно. Обычно, когда формируют коллекцию однотипных объектов, то и работают с этими объектами однотипно.

Цитата Сообщение от skilllab Посмотреть сообщение
Да нет у меня в классах методов))) нет. Одни свойства.
И НАД классами я никакой работы делать не буду. А только С классами (то бишь изменять свойства конкретного класса)
Чем вам визитёр не понравился? Вы не можете ввести методы Accept в свои классы? Это не изуродовало бы их и не попортило бы архитектуру (если таковая вообще имеет место).

А вообще, подругому никак не получалось сделать? Чтобы не бегать по коллекции и не выяснть кто есть кто?
0
Master of Orion
Эксперт .NET
 Аватар для Psilon
6102 / 4958 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
12.06.2017, 12:42
Цитата Сообщение от skilllab Посмотреть сообщение
ну так если имеем List<Figures> с Triangle, Circle, Square, Shape, и нужно пробежаться по листу по порядку и для каждого типа совершить получение свойства (или задание свойства) из класса (а свойство уникально для каждого класса), то и получится is и as же
Ну по-хорошему этого не должно быть, но если такое происходит, это должно быть в одном месте спрятано. Визиторы как раз для этого.
Цитата Сообщение от skilllab Посмотреть сообщение
Да нет у меня в классах методов))) нет. Одни свойства.
И НАД классами я никакой работы делать не буду. А только С классами (то бишь изменять свойства конкретного класса)
Почему это нельзя объединить в какой-нибудь метод типа ChangeSomething(IChangeInput input) и выполнить его над всеми элементами коллекции?
Цитата Сообщение от skilllab Посмотреть сообщение
Что typeOf() что is ...
И то и то не очень, но TypeOf выглядит поприличнее. По-моему это вполне заметно в количестве копипасты IHasMaterial в исходном коде.
Цитата Сообщение от skilllab Посмотреть сообщение
И ещё чуток.
Ключевое слово - относительно
0
Эксперт .NET
 Аватар для Usaga
14783 / 9557 / 1366
Регистрация: 21.01.2016
Сообщений: 36,033
12.06.2017, 12:43
Цитата Сообщение от skilllab Посмотреть сообщение
И ещё чуток.
Пожалуйста, перестаньте уже понимать слова буквально (не используете абстракцию => не ипользуете интерфейсы). Вы ввели интерфейсы для ваших объектов, чтобы абстрагироваться от их реальных типов, но это абстрагирование просто игнорируете. Выглядит так, как буд-то интефрейс был нужно только для того, чтобы можно было всё это в одну коллекцию сложить... Какое-то странное решение.
0
 Аватар для skilllab
296 / 236 / 58
Регистрация: 03.02.2011
Сообщений: 2,051
Записей в блоге: 1
12.06.2017, 12:46  [ТС]
Цитата Сообщение от Usaga Посмотреть сообщение
то и работают с этими объектами однотипно
так я и работаю однотипно с общими свойствами.
Ещё уточню: не для каждого класса VM требуется к примеру свойство "Площадь". Вон, у Line её просто не будет в модели. Хотя Line это тоже Figures.
Цитата Сообщение от Usaga Посмотреть сообщение
А вообще, подругому никак не получалось сделать?
Возвращаемся к одному большому толстому классу, где есть ВСЕ свойства. Просто где-то они реально будут (есть в модели), а где-то будут возвращать null или пустое значение? Тогда вообще не важно есть значение свойства или нет. Так?

Цитата Сообщение от Usaga Посмотреть сообщение
Вы не можете ввести методы Accept в свои классы?
Это к каждому свойству прицеплять метод? Чтоб ввести или взять значение.

Добавлено через 1 минуту
Цитата Сообщение от Usaga Посмотреть сообщение
Выглядит так
так я об этом)) и вы о том же))) я просто ищу правильный путь. Все говорят что это неправильный путь, но никто не говорит а как правильно. Визитер - погуглил, почитал. Выполнение методов над классами и в классах. Как это вяжется с назначением значения уникального для конкретного класса свойства - не понял
0
Эксперт .NET
 Аватар для Usaga
14783 / 9557 / 1366
Регистрация: 21.01.2016
Сообщений: 36,033
12.06.2017, 12:53
Цитата Сообщение от skilllab Посмотреть сообщение
Это к каждому свойству прицеплять метод? Чтоб ввести или взять значение.
К какому ещё свойству? Я же пример выше приводил. Вы же не просто свойство читаете. У вас для каждого типа объекта есть свой алгоритм обработки, так ведь? Вот эти алгоритмы и нужно разедлить по методам VisitLine, VisitRectangle и т.д. В каждом методе уже точно будет известо, что за объект имеет место быть и уже будут доступны все его "уникальные" свойства.

Цитата Сообщение от skilllab Посмотреть сообщение
Возвращаемся к одному большому толстому классу, где есть ВСЕ свойства.
Нет. Я не об этом. Может можно было объекты разложить по разным коллекциям, к примеру? Или ещё что. Просто не очень понятно, почему по сути разные вещи оказались все в одной кучке. Вы говорите, что работаете с данной коллекцией обобщённо и тут же вылазиет AS и IS. Как-то странно.
0
 Аватар для skilllab
296 / 236 / 58
Регистрация: 03.02.2011
Сообщений: 2,051
Записей в блоге: 1
12.06.2017, 13:02  [ТС]
Я, может, реально упускаю какую то фундаментальную составляющую, но вот одарю сотнями лайков за подсказку)))

C#
1
2
3
4
5
6
7
8
9
10
11
public class Horse
{
   public string Name { get; set; }
   public string Color { get; set; }
}
 
public class Rabbit
{
   public string Name { get; set; }
   public bool Tail { get; set; }
}
А теперь имеем List из этих классов (что именно применить к классам я сейчас не знаю, как их абстрагировать, это я и пытаюсь понять - сделать обобщённую коллекцию)
пробегаясь по листу хочу изменить именно у одной Horse свойство Color. У одной, по совпадению свойства Name с ранее определённой переменной.
Как?

Добавлено через 5 минут
Свойство Name (допустим сейчас) уникально.

Добавлено через 15 секунд
Свойство Name (допустим сейчас) уникально.
0
Master of Orion
Эксперт .NET
 Аватар для Psilon
6102 / 4958 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
12.06.2017, 13:04
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class ConditionalColorChangerVisitor
{
   public void Visit(string name, Horse horse)
   {
      if (horse.Name == name)
         horse.Color = Color.Red;
   }
 
   public void Visit(string name, Rabbit rabbit)
   {
      if (rabbit.Name == name)
         rabbit.Tail = !rabbit.Tail;
   }
}
 
public class Horse
{
   public string Name { get; set; }
   public string Color { get; set; }
 
   public void Accept(ConditionalColorChangerVisitor visitor) => visitor.Visit(this);
}
 
public class Rabbit
{
   public string Name { get; set; }
   public bool Tail { get; set; }
 
   public void Accept(ConditionalColorChangerVisitor visitor) => visitor.Visit(this);
}
 
 
...
 
var visitor = new ConditionalColorChangerVisitor();
foreach(var animal in animals)
   animal.Accept(visitor);
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
12.06.2017, 13:04

Обобщённые интерфейсы и классы
Здравствуйте, прошу помочь разобраться в следующем вопросе, у меня есть обобщённый класс class Myclass&lt;T&gt; : IMy&lt;T&gt; ...

Абстрактные классы и интерфейсы
Добрый день, какой смысл в C# был заложен в создание интерфейсов, а не использование абстрактных классов. Да я знаю отличия, что в...

Полиморфные классы и интерфейсы
Создать перечисления для представления дней недели. Вывести все значения на экран.

Интерфейсы и абстрактные классы
Всем привет! Помогите пожалуйста, недавно подкинули вопрос, который заинтересовал: что было бы если разработчики Майкрософт Icomparable...

Абстрактные классы и интерфейсы. Разница
Вот хоть убейте, не могу понять разницы между абстрактным классом и интерфейсом. До этого изучал C++, там не было интерфейсов, скорее всего...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
Беседа с ИИ о программистах, недопускающих к созданию и правке кода генеративные ИИ и причины этого
zorxor 21.09.2026
Раньше я радовался или получал некоторые эмоции, пусть небольшие, но всё же, от самого процесса написания кода, рекомпиляции и запуска, видя постепенное развитие программы и прочее. А теперь лень. . .
Мобильное приложение ColorStep
pavlinmavlin 17.09.2026
Реализовал приложение Красный, Зеленый, Синий в Unity3d + c#. Название изменил на ColorStep. Приложение прошло модерацию и теперь доступно для скачивания. Делал его сам, шаг за шагом — и вот,. . .
Запрет дублирования строк в табличной части
Maks 13.09.2026
Реализация из решения ниже выполнена на нетиповом справочнике "Нормы ТО" с табличной часть "Виды ТО", разработанного в КА2, со следующими реквизитами: - ВидТО (СправочникСсылка. ВидыТО); - ВидГСМ. . .
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр. Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала. Ниже прикреплён. . .
Программа опроса у.з. расходомера SLS-720F
Argus19 02.09.2026
Программа опроса у. з. расходомера SLS-720F Программа опрашивает один раз в минуту три ультразвуковых расходомера SLS-720F через интерфейс RS-485 по протоколу Modbus RTU. Опрашиваются регистры. . .
Hyper-V: Компьютер должен поддерживать доверенный платформенный модуль 2.0.
Maks 31.08.2026
При установке Windows 11 на виртуальную машину Hyper-V 2-го поколения вылезла такая ошибка: Решение: в параметрах виртуальной машины, в разделе "Безопасность" (Security) активировать флаг. . .
Архитектура биовида Стива в Майнкрафте: Зачем бонобо кубический каннибализм
anaschu 30.08.2026
Кубический Вагинокапитализм в Minecraft: Математический инвариант ОДУ и рок Стивов-бонобо Главная задача разработанной «Модели Всего» — наглядно продемонстрировать наличие системной «судьбы». . .
Оттачиваю умение писать js программы.
russiannick 30.08.2026
Проектом выходного дня стало написание Книги шифров Виженера. Итогом стала версия 200, синий туман. Синий туман назван так, потому что замораживает текст под собой. Нажатие синих кнопок управляют. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru