Форум программистов, компьютерный форум, киберфорум
Unity, Unity3D
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.84/25: Рейтинг темы: голосов - 25, средняя оценка - 4.84
4 / 3 / 1
Регистрация: 16.03.2020
Сообщений: 35

Проблема с наследованием методов класса

28.03.2020, 14:32. Показов 5150. Ответов 7
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Нужна помощь! Я загнан в тупик.
Уже упростил до минимума: создаю класс с неким методом check, наследую от класса и там переписываю этот метод. Объекты дочерних классов лежат в списке. И просто для каждого элемента списка вызываю этот метод check. При этом почему-то вызывается метод их родительского класса condition, а не новые переписанные методы. Вот код:

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
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
 
public class test_window : EditorWindow
{
    
    public List<condition> events = new List<condition>();
 
    
    [System.Serializable]
    public class condition
    {
        public virtual bool check()
        {
 
            Debug.Log("Fuck you, base condition");
            return false;
        }
    }
    [System.Serializable]
    public class transform_condition : condition
    {
        public GameObject obj;
        public Vector2 pos;
        public float rot;
 
        public transform_condition(GameObject obj, Vector2 pos, float rot)
        {
            this.obj = obj;
            this.pos = pos;
            this.rot = rot;
        }
 
        public override bool check()
        {
            Debug.Log("transform cheked");
            return true;
        }
    }
 
    public class join_condition : condition
    {
        public GameObject obj1, obj2;
 
        public join_condition(GameObject obj1, GameObject obj2)
        {
            this.obj1 = obj1;
            this.obj2 = obj2;
        }
 
        public override bool check()
        {
            Debug.Log("join checked");
            return true;
        }
    }
 
 
    [MenuItem("Window/test_window")]
 
    
    public static void ShowWindow()
    {
        GetWindow<test_window>("testing");
    }
 
    void OnGUI()
    {
 
        if (GUILayout.Button("Add condition"))
        {
            GameObject GO = Selection.gameObjects[0];
            events.Add(new transform_condition(GO, GO.transform.position, GO.transform.eulerAngles.z));
            events.Add(new join_condition(Selection.gameObjects[0], Selection.gameObjects[1]));
        }
    }
 
    private void Update()
    {
        if (EditorApplication.isPlaying)
        {
            Debug.Log(events.Count);
            foreach (condition the_cond in events)
            {
                if (the_cond.check())
                {
                    Debug.Log("oh yeah");
                }
            }
        }
 
    }
}
В этом коде всегда вылезает fuck you base condition, а надо, чтобы вызывались методы новых классов join_condition и transform_condition

Самое интересное, что в другом обычном скрипте, все работает как надо и вызываются методы именно Big_Dog и Small_Dog, хотя записано все так же:

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
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class animals : MonoBehaviour
{
    public List<Dogs> dog_list = new List<Dogs>();
    [System.Serializable]
    public class Dogs
    {
        public virtual bool voice()
        {
            Debug.Log("base class function");
            return false;
        }
    }
    [System.Serializable]
    public class Big_Dog : Dogs
    {
        public override bool voice()
        {
            Debug.Log("BRRRRR!!!");
            return true;
        }
    }
    [System.Serializable]
    public class Small_Dog : Dogs
    {
        public override bool voice()
        {
            Debug.Log("brrr....");
            return true;
        }
    }
    
    // Start is called before the first frame update
    void Start()
    {
        dog_list.Add(new Big_Dog());
        dog_list.Add(new Small_Dog());
    }
 
    // Update is called once per frame
    void Update()
    {
        foreach (Dogs the_dog in dog_list)
        {
            if (the_dog.voice())
            {
                Debug.Log("works with dogs");
            }
        }
    }
}
Здесь все четко: для одной собаки пишется ее BRRR!, для другой brr...

Вопрос: почему во втором работает, а в первом - нет??
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
28.03.2020, 14:32
Ответы с готовыми решениями:

Создать 2 класса с наследованием полей и методов
Экзамен по C#. Создать 2 класса с наследованием следующей структуры. 1: поля а и b, конструктор для их ввода; 2: методы fact,fib, вывести...

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

Проблема с наследованием
Здравствуйте, уважаемые Все! Столкнулся со следующей проблемой. Необходимо реализовать паттерн программирования &quot;Фабричный...

7
 Аватар для 1max1
3362 / 1775 / 1028
Регистрация: 26.10.2018
Сообщений: 5,204
28.03.2020, 14:45
По коду все правильно, может этот лог вылезает еще где-то в другом месте?
0
4 / 3 / 1
Регистрация: 16.03.2020
Сообщений: 35
28.03.2020, 15:35  [ТС]
Да нет вроде, больше нету такого..
Я посмотрел, где-то на этапе foreach ошибка должна быть, потому что для второго кода он правильно говорит, что the_dog это объект класса Big_Dog и Small_Dog соответственно, а вот в первом он считает, что the_cond это именно класс condition, отсюда и результат неправильный. Почему по разному происходит - не понятно.
0
 Аватар для 1max1
3362 / 1775 / 1028
Регистрация: 26.10.2018
Сообщений: 5,204
28.03.2020, 15:55
Ну и? https://www.youtube.com/watch?... e=youtu.be
1
 Аватар для wmysterio
295 / 244 / 128
Регистрация: 24.12.2014
Сообщений: 708
28.03.2020, 18:48
Цитата Сообщение от Rogdy Посмотреть сообщение
а вот в первом он считает, что the_cond это именно класс condition, отсюда и результат неправильный
Да нет, хоть и делается приведение типов в базовый "condition" в коде, должно вызываться также, как и во втором примере. Если бы в методах "check" было "base.check()", то тогда да, "fuck you base condition" вылезало бы Что-то там не то. Попробуйте класс "condition" и его метод "check" сделать абстрактными. Тогда не будет базовой реализации "check", но будет конкретная реализация в дочерних классах.
1
Эксперт .NETАвтор FAQ
 Аватар для Storm23
10427 / 5157 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
29.03.2020, 00:16
Лучший ответ Сообщение было отмечено Rogdy как решение

Решение

Цитата Сообщение от Rogdy Посмотреть сообщение
Вопрос: почему во втором работает, а в первом - нет??
Потому что в первом примере у вас скрипт наследник от EditorWindow, а во втором - наследник от MonoBehaviour.

Цитата Сообщение от Rogdy Посмотреть сообщение
При этом почему-то вызывается метод их родительского класса condition, а не новые переписанные методы
Это особенность работы сериализатора Unity.

Примерно происходит следующее:
Когда вы запустили приложение и клацнули кнопку - в список events заносятся объекты типа transform_condition и join_condition. В этот момент все работает хорошо и как нужно.
Затем вы останавливаете игру и запускаете ее снова. При этом, Unity сериализует ваш объект test_window и затем десериализует его снова (это стандартное поведение unity для EditorWindow).
Но в момент десериализации происходит следующее: сериализатор смотрит, что ваш список имеет тип List<condition>. То есть это список объектов типа condition. Поэтому он создает объекты типа condition и пытается десериализовать их из файла как condition. Таким образом, после десериализации, ваш список уже заполнен не исходными объектами, а объектами типа condition.

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

Ну а в целом, нужно учитывать, что сериализатор unity (как и XML сериалзация) - плохо дружит с наследованием.
2
 Аватар для 1max1
3362 / 1775 / 1028
Регистрация: 26.10.2018
Сообщений: 5,204
29.03.2020, 08:16
Storm23, может в новых версиях это пофиксили? Всё работает как надо, вроде...
https://www.youtube.com/watch?... e=youtu.be
0
4 / 3 / 1
Регистрация: 16.03.2020
Сообщений: 35
29.03.2020, 17:03  [ТС]
Всем спасибо! Сейчас буду пробовать!
1max1, насколько я понял, там не пофиксили, просто если добавлять в режиме play то действительно все хорошо, а вот если добавить в эдиторе, а потом запустить, то работает так себе

Добавлено через 4 часа 5 минут
А если классы в месте со списком перенести в monobehavior, а в editorwindow оставить только кнопку, это поможет?

Добавлено через 18 минут
Цитата Сообщение от Storm23 Посмотреть сообщение
это стандартное поведение unity для EditorWindow
а для monobehavior такая же фигня будет?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
29.03.2020, 17:03
Помогаю со студенческими работами здесь

Проблема с наследованием
Есть задание: Разработать три класса, которые следует связать между собой, используя наследование: 1. класс Product, который имеет три...

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

Проблема с наследованием класс
Есть класс class OkCancel : Form { public OkCancel(string qwert) { ... Button butOk...

Проблема с наследованием. css.
Вот в чем суть. У меня имеется див блок, у которого установлено свойство opasity:0.3; Проблема в том, что другой блок внутри этого...

Напишите реализацию методов, предоставляющих доступ к данным класса. Отобразите в программе работу этих методов
Реализация методов класса. Напишите реализацию методов, предоставляющих доступ к данным класса. Отобразите в программе...


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

Или воспользуйтесь поиском по форуму:
8
Ответ Создать тему
Новые блоги и статьи
Символьное дифференцирование
igorrr37 13.02.2026
/ * Логарифм записывается как: (x-2)log(x^2+2) - означает логарифм (x^2+2) по основанию (x-2). Унарный минус обозначается как ! */ #include <iostream> #include <stack> #include <cctype>. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru