[英]how do i call a subclass method on a superclass list containing subclasses
我很难说出我的标题,所以现在让我尝试详细说明。 首先这里是我的相关代码:
class Question
{
static bool checkFile(XElement q)
{
foreach (XElement a in q.Descendants())
{
if (a.Name.LocalName == "file")
{
return true;
}
}
return false;
}
protected string questionText;
protected List<File> files;
protected Question question;
public Question(XElement q)
{
questionText = q.Element("questiontext").Element("text").Value.ToString();
string name = q.Attribute("type").Value.ToString();
if (checkFile(q))
files.Add(new File(q));
}
}
class multichoice : Question
{
private List<string> answers;
public multichoice(XElement q)
: base(q)
{
foreach (XElement a in q.Elements())
{
if (a.Name.LocalName == "answer")
answers.Add(a.Element("text").Value.ToString());
}
}
public void writeQuestion(HtmlTextWriter writer)
{
writer.RenderBeginTag("p");
writer.Write("<strong>Multiple Choice: </strong>" + this.questionText);
writer.RenderEndTag();
writer.AddAttribute("type", "A");
writer.RenderBeginTag("ol");
foreach (string answer in answers)
{
writer.RenderBeginTag("li");
writer.Write(answer);
writer.RenderEndTag();
}
writer.RenderEndTag();
}
}
class truefalse : Question
{
public truefalse(XElement q)
: base(q)
{
}
public void writeQuestion(HtmlTextWriter writer)
{
writer.RenderBeginTag("strong");
writer.Write("True or False : ");
writer.RenderEndTag();
writer.Write(questionText);
}
}
因此,我正在创建多种类型的问题,它们都是“问题”的子类。 Question包含适用于每种类型问题的所有数据,这些子类包含对其唯一的方法,主要的方法是“ writeQuestion”。 现在,我正在尝试执行以下操作:
static List<Question> collectQuestions(XDocument doc)
{
XDocument xdoc = doc;
string elementName = null;
List<Question> questions = null;
foreach (XElement q in xdoc.Descendants("question"))
{
elementName = q.Attribute("type").Value.ToString();
if (elementName != "category")
continue;
if (elementName == "truefalse")
questions.Add(new truefalse(q)); //writeTrueFalse(writer, q);
else if (elementName == "calculatedmulti")
questions.Add(new calculatedmulti(q)); // writeCalculatedMulti(writer, q);
else if (elementName == "calculatedsimple")
questions.Add(new calculatedsimple(q)); // writeCalculatedSimple(writer, q);
else if (elementName == "ddwtos")
questions.Add(new Draganddrop(q)); //writeDragAndDrop(writer, q);
else if (elementName == "description")
questions.Add(new Description(q)); // writeDescription(writer, q);
else if (elementName == "essay")
questions.Add(new Essay(q)); // writeEssay(writer, q);
else if (elementName == "gapselect")
questions.Add(new Gapselect(q)); // writeGapSelect(writer, q);
else if (elementName == "matching")
questions.Add(new Matching(q)); // writeMatching(writer, q);
else if (elementName == "multichoice")
questions.Add(new multichoice(q)); // writeMultipleChoice(writer, q);
else if (elementName == "multichoiceset")
questions.Add(new Allornothing(q)); // writeAllOrNothing(writer, q);
else if (elementName == "numerical")
questions.Add(new Numerical(q)); // writeNumerical(writer, q);
else if (elementName == "shortanswer")
questions.Add(new shortanswer(q)); // writeShortAnswer(writer, q);
else
continue;
}
return questions;
}
questions = collectQuestions(someDocument);
foreach (Question question in questions)
{
question.writeQuestion(writer);
}
有没有一种方法可以在每个项目上调用writeQuestion? 现在,它当然会给出一个错误,即使每个子类都包含问题,但Questions不包含writeQuestion的定义。 如果我需要添加更多内容以进行澄清,请发表评论,因为我一直在重复修改它,所以我的代码有些混乱。 我非常喜欢使用此类课程,因此我可能缺少一些关键概念,请指出您所看到的任何内容,谢谢。
让基类abstract
,抽象添加WriteQuestion
成员的基类,然后override
它在每个具体的实现。
恕我直言,我会将您的代码分成更多类,以实现关注点的良好分离。
您的Question
类和专业化类(即派生类)不应该知道如何存储它们,也不应该知道如何将它们转换为HTML表示形式的某种格式。
我将定义一个名为XmlQuestionConverter
的类:
public class XmlQuestionConverter
{
public XmlQuestionConverter()
{
TypeToConvertMap = new Dictionary<Type, Action<Question, XElement>>
{
{ typeof(TrueFalseQuestion), new Action<Question, XElement>(ConvertTrueFalseFromXml) }
// other mappings...
};
}
private Dictionary<Type, Action<Question, HtmlTextWriter>> TypeToConvertMap
{
get;
}
// This dictionary maps element names to their type
private Dictionary<string, Type> QuestionTypeMap { get; } = new Dictionary<string, Type>()
{
{ "truefalse", typeof(TrueFalseQuestion) },
{ "multichoice", typeof(MultiChoiceQuestion) }
// And so on
};
public IList<Question> ConvertFromXml(XDocument questionsDocument)
{
// This will get all question elements and it'll project them
// into concrete Question instances upcasted to Question base
// class
List<Question> questions = questionsDocument
.Descendants("question")
.Select
(
element =>
{
Type questionType = QuestionTypeMap[q.Attribute("type").Value];
Question question = (Question)Activator.CreateInstance(questionType);
// Calls the appropiate delegate to perform specific
// actions against the instantiated question
TypeToConvertMap[questionType](question, element);
return question;
}
).ToList();
return questions;
}
private void ConvertTrueFalseFromXml(TrueFalseQuestion question, XElement element)
{
// Here you can populate specific attributes from the XElement
// to the whole typed question instance!
}
}
现在您可以将XDocument
转换为问题列表,并且我们准备使用HtmlTextWriter
将它们转换为HTML:
public class HtmlQuestionConverter
{
public HtmlQuestionConverter()
{
TypeToConvertMap = new Dictionary<Type, Action<Question, HtmlTextWriter>>
{
{ typeof(TrueFalseQuestion), new Action<Question, HtmlTextWriter>(ConvertTrueFalseToHtml) }
// other mappings...
};
}
private Dictionary<Type, Action<Question, HtmlTextWriter>> TypeToConvertMap
{
get;
}
public void ConvertToHtml(IEnumerable<Question> questions, HtmlTextWriter htmlWriter)
{
foreach (Question question in questions)
{
// Calls the appropiate method to turn the question
// into HTML using found delegate!
TypeToConvertMap[question.GetType()](question, htmlWriter);
}
}
private void ConvertTrueFalseToHtml(Question question, HtmlTextWriter htmlWriter)
{
// Code to write the question to the HtmlTextWriter...
}
}
这样,我根本看不到您需要多态性:
XmlQuestionConverter xmlQuestionConverter = new XmlQuestionConverter();
IList<Question> questions = xmlQuestionConverter.ConvertFromXml(xdoc);
HtmlQuestionConverter htmlQuestionConverter = new HtmlQuestionConverter();
htmlQuestionConverter.ConvertToHtml(questions, htmlWriter);
注意:我无法尝试执行此代码,而且我不确定100%是否会工作,但这是了解如何清晰地关注代码实现代码的一个好的开始! 您可能需要做一些调整,以使我的代码适应您的实际用例。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.