вызвать функцию класса на экземпляре класса - PullRequest
0 голосов
/ 02 июля 2018

У меня есть некоторый код, который генерирует ответы на основе пользовательского ввода. Но в некоторых случаях мне нужно обновить значения позже, вызвав SetAnswers Но когда я компилирую свой код, я получаю следующую ошибку:

NullReferenceException: ссылка на объект не установлена ​​для экземпляра объекта

Я получаю эту ошибку на линии, отмеченной стрелкой.
Смотрите мой код ниже:

public class Generate_Questions : MonoBehaviour{

public Question q5, q4;


void Start(){

    q4 = create_question("Select object to edit", EXTERNAL);
    Visual_Question vq1 = new Visual_Question(1, q4, new vector(1,1,1), Ui, Canvas);
    vq1.draw_question();
}

void Update(){

}




   public class Visual_Question : Generate_Questions{

        public Visual_Question(int order_id, Question q, Vector2 loc, Dictionary<string, RectTransform> ui, RectTransform canvas){
        }

        public void draw_question(){
            q4.SetAnswers(new Answer[]{ <--------- this generates the error. 
                new Answer(null, "Select an option")
            });
        }
    }


    public class Question{

        public string text;
        public int answers_loc;
        public List<Answer> answers;

        public Question(string q_text, int answers_loc){
            answers = new List<Answer>();
            this.text = q_text;
            this.answers_loc = answers_loc;
        }

        public void SetAnswers(Answer[] c_answers){
            foreach(Answer answer in c_answers){
                this.answers.Add(answer);
            }
        }

        public bool CheckIfAnswersAvailable(){
            if(answers.Count > 0){
                return true;
            }else{
                return false;
            }
        }

        public int QuestionLocation(){
            return answers_loc;
        }
    }

    public Question create_question(string text, int a_type){
        Question Q = new Question(text, a_type);
        return Q;
    }

    public interface IAnswer{
        string GetText();
        string GetDataType();
        object GetValue();
        Question GetNextQuestion();
    }

    public class Answer : IAnswer{

        public string text;
        public Question next = null;
        public int? action = null;
        public Element obj = null;
        public string property = null;
        public float? value = null;

        public Answer(Question next, string text){
            this.text = text;
            this.next = next;
        }

        public Answer(Question next, string text, Element obj, int? action){
            this.action = action;
            this.text = text;
            this.next = next;
            this.obj = obj;
        }

        public Answer(Question next, string text, Element obj, int? action, string property, float? value){
            this.action = action;
            this.next = next;
            this.text = text;
            this.obj = obj;
            this.property = property;
            this.value = value;
        }

        public string GetText(){
            return text;
        }

        public string GetDataType(){
            throw new System.NotImplementedException();
        }

        public object GetValue(){
            return value;
        }

        public Question GetNextQuestion(){
            return next;
        }
    }
}

как мне решить эту проблему? Я полный новичок в C #. Так что на мой вопрос уже можно ответить, но я просто не знаю, что я ищу.

Ответы [ 3 ]

0 голосов
/ 02 июля 2018

Ваш класс Visual_Question является производным от Generate_Questions, поэтому элемент q4 , который вы используете en draw_question, не инициализирован. Это не элемент Generated_Questions, а элемент Visual_Question, который не инициализирован.

0 голосов
/ 02 июля 2018

В Generate_Questions вы создаете новый экземпляр Visual_Question, а затем немедленно вызываете draw_question для этого нового экземпляра. Теперь у вас есть 2 экземпляров вопроса (оба получены из Generate_Questions), но только у одного из них был метод Start, который инициализирует q4. Однако если вы попытаетесь вызвать Start из своего второго экземпляра, вы попадете в бесконечную серию рекурсивных вызовов и быстро завершите работу с другой ошибкой (переполнение стека в этом случае).

Одна проблема с текущим кодом состоит в том, что Generate_Questions звучит больше как действие, чем класс. Я бы предложил убрать наследование из Visual_Question и сделать его интерфейсом, который вы бы реализовали на Question. Question, вероятно, следует удалить метод create_question. Это, вероятно, относится к сценарию MonoBehavior (технически это фабричный метод - посмотрите фабричный шаблон - я не буду вдаваться в подробности, так как это тема для начинающих).

Что-то вроде (очевидно, не завершено):

public class Generate_Questions : MonoBehaviour
{
    private IVisualQuestion q4;

    void Start() 
    {
        q4 = new Question("Select object to edit", EXTERNAL);
        q4.DrawQuestion(new vector(1,1,1), Ui, Canvas)
    }

    void Update() {}
}

public interface IVisualQuestion
{
    void DrawQuestion(Vector2 loc, Dictionary<string, RectTransform> ui, RectTransform canvas);
}

public class Question : IVisualQuestion
{
    // ... insert the Question constructor and code here ...

    // Implement VisualQuestion interface
    public void DrawQuestion(Vector2 loc, Dictionary<string, RectTransform> ui, RectTransform canvas)
    {
        this.SetAnswers(new Answer[]{new Answer(null, "Select an option")});
    }
}

В общем, вам, вероятно, не нужно наследование. Когда вы узнаете больше о C #, вы обнаружите, что когда наследование поможет, это станет ясно. Чаще всего использование интерфейса - гораздо лучший и гибкий подход. Как заметил комментатор, вы, вероятно, не хотите наследовать от MonoBehavior. Это действительно нужно только для классов, которые Unity Engine будет обрабатывать напрямую.

Еще одно примечание: в C # принято называть методы, переменные и т. Д. В PascalCase, не используя подчеркивания для разделения слов.

0 голосов
/ 02 июля 2018

Я предполагаю, что IAnswer[] - это интерфейс, и, поскольку вы пытаетесь инициализировать абстрактный объект, вы получаете это исключение времени выполнения

NullReferenceException: ссылка на объект не установлена ​​для экземпляра объекта

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...