#c# #class #inheritance #derived-class
#c# #класс #наследование #производный класс
Вопрос:
У меня есть следующий код, который представляет ребра и узлы графа (упрощенный для вопроса):
public class Node
{
}
public class Edge
{
public Node Source { get; set; }
public Node Target { get; set; }
}
Теперь я хочу расширить эти классы для описания моей топологии:
public class MineNode : Node
{
public double FanPressure { get; set; }
}
public class MineTunnel : Edge
{
public double Length { get; set; }
public double CrossSectionArea { get; set; }
public MineTunnel()
{
Source = new MineNode();
Target = new MineNode();
}
}
Проблема в том, что я хочу получить доступ к дополнительным данным, предоставляемым MineNode
при использовании Source
и Target
свойств, но я могу получить доступ только к Node
полям, потому что они объявлены в базовом классе:
MineTunnel t = new MineTunnel();
Console.WriteLine(t.Source.FanPressure); //Error
Единственный способ получить доступ FanPressure
— привести Source
к MineNode
, но таким образом код становится уродливым.
Console.WriteLine(((MineNode)t.Source).FanPressure); //OK
Возможно, другим способом является использование каких-либо обобщений в объявлении базового класса. Но я не уверен, что это хорошая практика в моей ситуации.
Итак, как я могу решить такую проблему — расширить функциональность полей базового класса?
Спасибо.
Ответ №1:
Вы могли бы определить свой Edge
тип как универсальный, с ограничениями:
public class Edge<TNode> where TNode: Node
{
public TNode Source { get; set; }
public TNode Target { get; set; }
}
С помощью которого вы могли бы переопределить свой MineTunnel
тип как:
public class MineTunnel : Edge<MineNode>
{
// Stuff
}
Ответ №2:
Я думаю, что дженерики — это правильный путь…
Попробуйте это:
public class Node
{
}
public class Edge<S, T>
where S : Node
where T : Node
{
public S Source { get; set; }
public T Target { get; set; }
}
Затем вы можете расширить классы Node и Edge с помощью:
public class MineNode : Node
{
public double FanPressure { get; set; }
}
public class MineTunnel : Edge<MineNode, MineNode>
{
public double Length { get; set; }
public double CrossSectionArea { get; set; }
public MineTunnel()
{
Source = new MineNode();
Target = new MineNode();
}
}
Пожалуйста, поправьте меня, если это неправильно или не работает … 🙂
MineTunnel t = new MineTunnel();
Console.WriteLine(t.Source.FanPressure); // Now this works without errors ;)
Комментарии:
1. Почему у вас есть узел, расширяющий границы?
2. О, извините, это было не намеренно. Думаю, это проскользнуло туда, когда я писал заголовок класса
3. Почему исходный и целевой узлы имеют разные типы?
4. Потому что я думал, что для ребра было бы возможно перейти от т.е. MineNode к YourNode. Вы могли бы указать разные типы для источника и назначения.
5. Разные универсальные типы — это нормально, но я все равно всегда буду использовать одно и то же. Все ответы хороши и правильны, но вы были немного быстрее.