C#继承问题:Grua类ToString()未正确显示父类Camiones的Dominio属性
问题分析
你遇到的问题其实源于两个常见的C#继承误区:
1. 混淆了类继承和实例属性值的关系
继承是类层面的特性——Grua类继承了Camiones类的属性定义(Marca、Dominio),但每个实例的属性值是完全独立的!你创建的nuevoCamion(Camiones实例)和nuevaGrua(Grua实例)是两个毫无关联的对象,nuevaGrua不会自动继承nuevoCamion的Marca或Dominio值,必须手动给它赋值。
2. 可能在Grua类中重复定义了Marca属性(隐藏父类属性)
如果你的Grua类里重新声明了Marca属性(比如写了public string Marca { get; set; }),这会隐藏父类Camiones的Marca属性:你给nuevaGrua.Marca赋值时,实际操作的是子类自己的Marca,而父类的Marca还是默认的null。不过根据你的描述,Marca显示的是Grua设置的值,更可能是你没有重复定义属性,但误解了实例属性的独立性。
解决方案
步骤1:修正类的定义(避免隐藏父类属性)
确保Grua类不重复定义父类已有的属性,直接继承使用父类的属性:
// 抽象基类 public abstract class Equipos { public abstract override string ToString(); } // 父类Camiones public class Camiones : Equipos { // 父类的属性,子类Grua直接继承使用 public string Marca { get; set; } public string Dominio { get; set; } public override string ToString() { return $"Camión: Marca={Marca}, Dominio={Dominio}"; } } // 子类Grua,正确继承Camiones public class Grua : Camiones { // 只定义子类独有的属性 public decimal Peso { get; set; } public int Altura { get; set; } public decimal PrecioHora { get; set; } // 正确调用父类ToString方法,再追加子类属性 public override string ToString() { return $"{base.ToString()}, Peso={Peso}kg, Altura={Altura}m, Precio/hora={PrecioHora:C}"; } }
步骤2:正确初始化Grua实例的属性
如果你希望Grua实例的Dominio有值,必须显式给它赋值(因为它和Camiones实例nuevoCamion是独立对象):
// Camiones实例正常使用 var nuevoCamion = new Camiones { Marca = "Volvo", Dominio = "ABC-123" }; Console.WriteLine(nuevoCamion.ToString()); // 输出:Camión: Marca=Volvo, Dominio=ABC-123 // Grua实例,显式设置父类属性和子类属性 var nuevaGrua = new Grua { Marca = "Mercedes", // 这里赋值的是继承自Camiones的Marca属性 Dominio = "XYZ-789", // 必须显式设置Dominio,否则会为空 Peso = 15000, Altura = 25, PrecioHora = 120.5m }; Console.WriteLine(nuevaGrua.ToString()); // 输出:Camión: Marca=Mercedes, Dominio=XYZ-789, Peso=15000kg, Altura=25m, Precio/hora=$120.50
(可选)通过构造函数简化属性初始化
如果想避免忘记设置父类属性,可以给Camiones添加构造函数,让Grua调用父类构造函数来初始化继承的属性:
// 给Camiones添加构造函数 public class Camiones : Equipos { public string Marca { get; set; } public string Dominio { get; set; } // 带参数的构造函数,强制初始化核心属性 public Camiones(string marca, string dominio) { Marca = marca; Dominio = dominio; } // 保留无参构造(如果需要创建未初始化的实例) public Camiones() { } public override string ToString() { return $"Camión: Marca={Marca}, Dominio={Dominio}"; } } // Grua的构造函数调用父类构造 public class Grua : Camiones { public decimal Peso { get; set; } public int Altura { get; set; } public decimal PrecioHora { get; set; } public Grua(string marca, string dominio, decimal peso, int altura, decimal precioHora) : base(marca, dominio) // 调用父类构造函数初始化Marca和Dominio { Peso = peso; Altura = altura; PrecioHora = precioHora; } public override string ToString() { return $"{base.ToString()}, Peso={Peso}kg, Altura={Altura}m, Precio/hora={PrecioHora:C}"; } } // 使用时必须传入父类属性,避免遗漏 var nuevaGrua = new Grua("Mercedes", "XYZ-789", 15000, 25, 120.5m);
关键总结
- 继承是类的定义层面的复用,不是实例属性值的复用,每个对象的属性值都是独立的。
- 子类不要重复定义父类已有的属性,否则会隐藏父类属性,导致逻辑混乱。
- 如果需要子类实例拥有父类属性的特定值,必须显式赋值(或通过构造函数强制传入)。
内容的提问来源于stack exchange,提问作者le0nicolas
相关产品推荐
相关产品推荐

