C#继承场景下子类如何使用自身discount变量计算应付款
嘿,这个问题我之前也踩过坑!核心原因很明确:你基类的discount是私有字段,子类完全访问不到它;而且你在子类里又重新定义了一个同名的私有discount——这俩是完全独立的变量,基类的owes()方法只会调用自己的那个0折扣值,所以子类的10%折扣根本没被用到。
下面给你两种最贴合面向对象设计的修复方案:
方案1:把基类的discount改成protected,子类直接复用
把基类里的private float discount = 0;改成protected float discount = 0;,这样子类就能直接继承并修改这个字段的值,不需要再重新定义同名变量。
修改后的基类Customer
using System; namespace Customer { public class Customer { // 改为protected,允许子类访问和修改 protected float discount = 0; public string name; public float balance; public string addr1; public string addr2; public string addr3; public Customer(string name, float balance, string addr1, string addr2, string addr3) { this.name = name; this.balance = balance; this.addr1 = addr1; this.addr2 = addr2; this.addr3 = addr3; } public virtual float owes() { // 简化计算:原价*(1-折扣率) = 应付款 return Math.Abs(balance * (1 - discount)); } public override string ToString() { return String.Format("{0}\n{1}\n{2}\n{3}\nBalance: {4}\nDiscount: {5}%\nAmount due: {6:0.00}", name, addr1, addr2, addr3, balance, discount * 100, owes()); } } }
修改后的子类ValuedCustomer
using System; namespace Customer { public class ValuedCustomer : Customer { // 删掉子类自己的discount字段,直接用基类的 public ValuedCustomer(string name, float balance, string addr1, string addr2, string addr3) : base(name, balance, addr1, addr2, addr3) { // 直接给基类的discount赋值10% this.discount = 0.1f; } // 如果不需要特殊格式,这个ToString重写可以删掉,基类的已经能正确显示 public override string ToString() { return String.Format("{0}\n{1}\n{2}\n{3}\nBalance: {4}\nDiscount: {5}%\nAmount due: {6:0.00}", name, addr1, addr2, addr3, balance, discount * 100, owes()); } } }
方案2:用受保护的虚拟属性封装折扣(更符合封装原则)
如果不想直接暴露字段,可以把折扣封装成受保护的虚拟属性,子类通过重写属性来提供自己的折扣值,这种方式更安全。
基类修改核心部分
// 用虚拟属性代替私有字段,隐藏实现细节 protected virtual float Discount => 0; public virtual float owes() { return Math.Abs(balance * (1 - Discount)); }
子类修改核心部分
public class ValuedCustomer : Customer { // 重写属性返回10%折扣 protected override float Discount => 0.1f; public ValuedCustomer(string name, float balance, string addr1, string addr2, string addr3) : base(name, balance, addr1, addr2, addr3) { } }
验证结果
不管用哪种方案,运行代码后都会得到你预期的输出:
Jimmy 22 Main Street Naas Kildare Balance: 100 Discount: 0% Amount due: 100.00 Lucy 23 Main Street Roosky Roscommon Balance: 100 Discount: 10% Amount due: 90.00 Fred 24 Main Street Sneem Kerry Balance: 200 Discount: 0% Amount due: 200.00
内容的提问来源于stack exchange,提问作者webchatowner
相关产品推荐
相关产品推荐

