You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:31:40