在类的实例上调用类的函数

时间:2018-07-02 08:49:40

标签: function class oop unity3d

我有一些代码可以根据用户输入生成答案。但是在某些情况下,我需要稍后通过调用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 :(得分:1)

我假设IAnswer[]是一个接口,并且由于您尝试初始化抽象对象,因此会遇到运行时异常

  

NullReferenceException:对象引用未设置为对象的实例

如果要创建IAnswer对象的实例,则必须像类或结构一样重新构造它。

答案 1 :(得分:0)

您的Visual_Question类是从Generate_Questions派生的,因此您使用en draw_question的成员 q4 未初始化。这不是Generated_Questions的成员,而是未初始化的Visual_Question的成员。

答案 2 :(得分:0)

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引擎将直接处理的类。

另一注:C#中的约定是在PascalCase中命名方法,变量等,而不使用下划线分隔单词。