c#关于类,对象的例子实现

此文是根据类和对象 - C# 基础教程 | Microsoft Learn进行实践的笔记。

一.题目

BankAccount 类表示银行帐户。对账户进行分类

  1. 用一个 10 位数唯一标识银行帐户。
  2. 用字符串存储一个或多个所有者名称。
  3. 可以检索余额。
  4. 接受存款。
  5. 接受取款。
  6. 初始余额必须是 >=0
  7. 取款后的余额不能是负数。(信用卡除外)

二.代码实现

2.1 Transaction类

2.1.1 全类完整代码:

此类用来记录每笔流水

namespace Classes;

public class Transaction
{
    public decimal Amount { get; }
    public DateTime Date { get; }
    public string Notes { get; }

    public Transaction(decimal amount, DateTime date, string note)
    {
        Amount = amount;
        Date = date;
        Notes = note;
    }
}

2.2 BankAccount 类

2.2.1 全类完整代码:

namespace Classes;

public class BankAccount
{
    //    用一个 10 位数唯一标识银行帐户。
    //用字符串存储一个或多个所有者名称。
    //可以检索余额。
    //接受存款。
    //接受取款。
    //初始余额必须是正数。
    //取款后的余额不能是负数。
    private static int accountNumberSeed = 1234567890;
    private readonly decimal _minimumBalance;

    public string Number { get; }
    public string Owner { get; set; }
    public decimal Balance { get
        {
            decimal balance = 0;
            foreach (var item in allTransactions)
            {
                balance += item.Amount;
            }

            return balance;
        }
    }
 


    //public BankAccount(string name, decimal initialBalance)
    //{        
    //    this.Owner = name;
    //    this.Number = accountNumberSeed.ToString();
    //    accountNumberSeed++;

    //    MakeDeposit(initialBalance, DateTime.Now, "Initial balance");
    //}

    

    public BankAccount(string name, decimal initialBalance) : this(name, initialBalance, 0) { }

    public BankAccount(string name, decimal initialBalance, decimal minimumBalance)
    {
        Number = accountNumberSeed.ToString();
        accountNumberSeed++;

        Owner = name;
        _minimumBalance = minimumBalance;
        if (initialBalance > 0)
            MakeDeposit(initialBalance, DateTime.Now, "Initial balance");
    }

    /// <summary>
    /// virtual 关键字在基类中声明一个方法,让派生类可以为该方法提供不同的实现。 在 virtual 方法种,任何派生类都可以选择重新实现。
    /// 派生类使用 override 关键字定义新的实现。 通常将其称为“重写基类实现”。 virtual 关键字指定派生类可以重写此行为。 
    /// 还可以声明 abstract 方法,让派生类必须在其中重写此行为。 基类不提供 abstract 方法的实现。 
    /// </summary>
    public virtual void PerformMonthEndTransactions() { }

    private List<Transaction> allTransactions = new List<Transaction>();
    public void MakeDeposit(decimal amount, DateTime date, string note)
    {
        if (amount <= 0)
        {
            throw new ArgumentOutOfRangeException(nameof(amount), "Amount of deposit must be positive");
        }
        var deposit = new Transaction(amount, date, note);
        allTransactions.Add(deposit);
    }

    //public void MakeWithdrawal(decimal amount, DateTime date, string note)
    //{
    //    if (amount <= 0)
    //    {
    //        throw new ArgumentOutOfRangeException(nameof(amount), "Amount of withdrawal must be positive");
    //    }
    //    if (Balance - amount < _minimumBalance)
    //    {
    //        throw new InvalidOperationException("Not sufficient funds for this withdrawal");
    //    }
    //    var withdrawal = new Transaction(-amount, date, note);
    //    allTransactions.Add(withdrawal);
    //}

    public void MakeWithdrawal(decimal amount, DateTime date, string note)
    {
        if (amount <= 0)
        {
            throw new ArgumentOutOfRangeException(nameof(amount), "Amount of withdrawal must be positive");
        }
        Transaction? overdraftTransaction = CheckWithdrawalLimit(Balance - amount < _minimumBalance);
        Transaction? withdrawal = new(-amount, date, note);
        allTransactions.Add(withdrawal);
        if (overdraftTransaction != null)
            allTransactions.Add(overdraftTransaction);
    }

    protected virtual Transaction? CheckWithdrawalLimit(bool isOverdrawn)
    {
        if (isOverdrawn)
        {
            throw new InvalidOperationException("Not sufficient funds for this withdrawal");
        }
        else
        {
            return default;
        }
    }

    public string GetAccountHistory()
    {
        var report = new System.Text.StringBuilder();

        decimal balance = 0;
        report.AppendLine("Date\t\tAmount\tBalance\tNote");
        foreach (var item in allTransactions)
        {
            balance += item.Amount;
            report.AppendLine($"{item.Date.ToShortDateString()}\t{item.Amount}\t{balance}\t{item.Notes}");
        }

        return report.ToString();
    }
}

2.2.2 具体讲解:

 其中包含了银行账户号码,用户,余额,以及此张卡最小的金额数(当卡是信用卡的时候,欠的金额后的余额)这四个属性。


    private static int accountNumberSeed = 1234567890;
    private readonly decimal _minimumBalance;

    public string Number { get; }
    public string Owner { get; set; }
    public decimal Balance { get
        {
            decimal balance = 0;
            foreach (var item in allTransactions)
            {
                balance += item.Amount;
            }

            return balance;
        }
    }
 

 MakeWithdrawal取钱,MakeDeposit存钱

存钱和取钱的时候需要确保存钱的金额是大于0的,不然抛出异常。

取钱的特殊处理是,在信用卡有时候可以借钱,余额为负数只要在额度内,还可以借钱,不收费。但是如果超过了额度,仍然可以借钱,但是需要收取费用。这里的有两笔交易,交易可以为空,或者生成一个Transation的对象(因为计算余额的时候,是遍历Transaction的金额并进行相加)

Transaction? overdraftTransaction = CheckWithdrawalLimit(Balance - amount < _minimumBalance);
Transaction? withdrawal = new(-amount, date, note);

这样返回的有时候是null,有时候是一个Transaction的对象。

注意这个CheckWithdrawalLimit在LineOfCreditAccount类中重写了。

这里CheckWithdrawalLimit 添加的方法是 protected,这意味着只能从派生类中调用它。 该声明会阻止其他客户端调用该方法。 它还是 virtual 的,因此派生类可以更改行为。 返回类型为 Transaction?。    ? 批注指示该方法可能返回 null。 


    private List<Transaction> allTransactions = new List<Transaction>();
    public void MakeDeposit(decimal amount, DateTime date, string note)
    {
        if (amount <= 0)
        {
            throw new ArgumentOutOfRangeException(nameof(amount), "Amount of deposit must be positive");
        }
        var deposit = new Transaction(amount, date, note);
        allTransactions.Add(deposit);
    }

    //public void MakeWithdrawal(decimal amount, DateTime date, string note)
    //{
    //    if (amount <= 0)
    //    {
    //        throw new ArgumentOutOfRangeException(nameof(amount), "Amount of withdrawal must be positive");
    //    }
    //    if (Balance - amount < _minimumBalance)
    //    {
    //        throw new InvalidOperationException("Not sufficient funds for this withdrawal");
    //    }
    //    var withdrawal = new Transaction(-amount, date, note);
    //    allTransactions.Add(withdrawal);
    //}

    public void MakeWithdrawal(decimal amount, DateTime date, string note)
    {
        if (amount <= 0)
        {
            throw new ArgumentOutOfRangeException(nameof(amount), "Amount of withdrawal must be positive");
        }
        Transaction? overdraftTransaction = CheckWithdrawalLimit(Balance - amount < _minimumBalance);
        Transaction? withdrawal = new(-amount, date, note);
        allTransactions.Add(withdrawal);
        if (overdraftTransaction != null)
            allTransactions.Add(overdraftTransaction);
    }

    protected virtual Transaction? CheckWithdrawalLimit(bool isOverdrawn)
    {
        if (isOverdrawn)
        {
            throw new InvalidOperationException("Not sufficient funds for this withdrawal");
        }
        else
        {
            return default;
        }
    }

BankAccount()构造函数是与类同名的成员。 用于初始化相应类类型的对象。会根据参数选择不同的构造方法,这称作构造函数的重载。   (构造方法具体可以参考:(7条消息) 什么是构造方法,构造方法的特征,作用_羡羡ˇ的博客-CSDN博客_什么是构造方法?构造方法有哪些特点?


    public BankAccount(string name, decimal initialBalance) : this(name, initialBalance, 0) { }

    public BankAccount(string name, decimal initialBalance, decimal minimumBalance)
    {
        Number = accountNumberSeed.ToString();
        accountNumberSeed++;

        Owner = name;
        _minimumBalance = minimumBalance;
//初始余额大于0等于你存进了第一笔钱
        if (initialBalance > 0)
            MakeDeposit(initialBalance, DateTime.Now, "Initial balance");
    }

第一个构造函数适用于储蓄卡

第二个适用于借记卡


    public string GetAccountHistory()
    {
        var report = new System.Text.StringBuilder();

        decimal balance = 0;
        report.AppendLine("Date\t\tAmount\tBalance\tNote");
        foreach (var item in allTransactions)
        {
            balance += item.Amount;
            report.AppendLine($"{item.Date.ToShortDateString()}\t{item.Amount}\t{balance}\t{item.Notes}");
        }

        return report.ToString();
    }

上面  记录所有交易

2.3 不同类型的帐户的类

分为此三类

  • 在每个月的月末获得利息的红利帐户。
  • 余额可以为负,但存在余额时会产生每月利息的信用帐户。
  • 以单笔存款开户且只能用于支付的预付礼品卡帐户。 可在每月初重新充值一次。

其中的每个类都从其共享的基类( BankAccount 类)继承共享的行为。 为的每个派生类中的新增和不同功能编写实现。 这些派生类已具有 BankAccount 类中定义的所有行为。

 virtual 关键字在基类中声明一个方法,让派生类可以为该方法提供不同的实现。 在 virtual 方法种,任何派生类都可以选择重新实现。 派生类使用 override 关键字定义新的实现。 通常将其称为“重写基类实现”。 virtual 关键字指定派生类可以重写此行为。 还可以声明 abstract 方法,让派生类必须在其中重写此行为。 基类不提供 abstract 方法的实现。

2.3.1 InterestEarningAccount 

using Classes;
//红利帐户:
//将获得月末余额 5 % 的额度
public class InterestEarningAccount : BankAccount
{
	public InterestEarningAccount(string name, decimal initialBalance) : base(name, initialBalance)
    {
    }
    /// <summary>
    /// 派生类使用 override 关键字定义新的实现
    /// </summary>
    public override void PerformMonthEndTransactions()
    {
        if (Balance > 500m)
        {
            decimal interest = Balance * 0.05m;
            MakeDeposit(interest, DateTime.Now, "apply monthly interest");
        }
    }
}

2.3.2 GiftCardAccount 

using Classes;

//每月最后一天,可以充值一次指定的金额
public class GiftCardAccount : BankAccount
{

    private readonly decimal _monthlyDeposit = 0m;

    public GiftCardAccount(string name, decimal initialBalance, decimal monthlyDeposit = 0) : base(name, initialBalance)
        => _monthlyDeposit = monthlyDeposit;

    public override void PerformMonthEndTransactions()
    {
        if (_monthlyDeposit != 0)
        {
            MakeDeposit(_monthlyDeposit, DateTime.Now, "Add monthly deposit");
        }
    }

}

2.3.3 LineOfCreditAccount 

using Classes;

//信用帐户:
//余额可以为负,但不能大于信用限额的绝对值。
//如果月末余额不为 0,每个月都会产生利息。
//将在超过信用限额的每次提款后收取费用
public class LineOfCreditAccount : BankAccount
{
	public LineOfCreditAccount(string name, decimal initialBalance) : base(name, initialBalance)
    {
        if (Balance < 0)
        {
            // Negate the balance to get a positive interest charge:
            decimal interest = -Balance * 0.07m;
            MakeWithdrawal(interest, DateTime.Now, "Charge monthly interest");
        }

    }

    public LineOfCreditAccount(string name, decimal initialBalance, decimal creditLimit) : base(name, initialBalance, -creditLimit)
    {
    }

    // 对超过限额的取款进行收费,而不是拒绝交易。
    protected override Transaction? CheckWithdrawalLimit(bool isOverdrawn) =>
    isOverdrawn
    ? new Transaction(-20, DateTime.Now, "Apply overdraft fee")
    : default;
}

2.4 主程序

namespace Classes
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");

            var account = new BankAccount("<name>", 1000);
            Console.WriteLine($"Account {account.Number} was created for {account.Owner} with {account.Balance} initial balance.");

            account.MakeWithdrawal(500, DateTime.Now, "Rent payment");
            Console.WriteLine(account.Balance);
            account.MakeDeposit(100, DateTime.Now, "Friend paid me back");
            Console.WriteLine(account.Balance);

            Console.WriteLine(account.GetAccountHistory());


            var account1 = new BankAccount("lianhua", 1040);
            Console.WriteLine($"Account {account1.Number} was created for {account1.Owner} with {account1.Balance} initial balance.");
            Console.WriteLine(account1.GetAccountHistory());
            Console.WriteLine("_______________________________________");


            var giftCard = new GiftCardAccount("gift card", 100, 50);
            Console.WriteLine($"Account {giftCard.Number} was created for {giftCard.Owner} with {giftCard.Balance} initial balance.");
            giftCard.MakeWithdrawal(20, DateTime.Now, "get expensive coffee");
            giftCard.MakeWithdrawal(50, DateTime.Now, "buy groceries");
            giftCard.PerformMonthEndTransactions();
            // can make additional deposits:
            giftCard.MakeDeposit(27.50m, DateTime.Now, "add some additional spending money");
            Console.WriteLine(giftCard.GetAccountHistory());

            var savings = new InterestEarningAccount("savings account", 10000);
            Console.WriteLine($"Account {savings.Number} was created for {savings.Owner} with {savings.Balance} initial balance.");
            savings.MakeDeposit(750, DateTime.Now, "save some money");
            savings.MakeDeposit(1250, DateTime.Now, "Add more savings");
            savings.MakeWithdrawal(250, DateTime.Now, "Needed to pay monthly bills");
            savings.PerformMonthEndTransactions();
            Console.WriteLine(savings.GetAccountHistory());

            Console.WriteLine("____________________________");
            var lineOfCredit1 = new LineOfCreditAccount("line of credit", 0);
            Console.WriteLine($"Account {lineOfCredit1.Number} was created for {lineOfCredit1.Owner} with {lineOfCredit1.Balance} initial balance.");

            var lineOfCredit = new LineOfCreditAccount("line of credit", 0, 2000);
            Console.WriteLine($"Account {lineOfCredit.Number} was created for {lineOfCredit.Owner} with {lineOfCredit.Balance} initial balance.");

            // How much is too much to borrow?
            lineOfCredit.MakeWithdrawal(1000m, DateTime.Now, "Take out monthly advance");
            lineOfCredit.MakeDeposit(50m, DateTime.Now, "Pay back small amount");
            lineOfCredit.MakeWithdrawal(5000m, DateTime.Now, "Emergency funds for repairs");
            lineOfCredit.MakeDeposit(150m, DateTime.Now, "Partial restoration on repairs");
            lineOfCredit.PerformMonthEndTransactions();
            Console.WriteLine(lineOfCredit.GetAccountHistory());
             Test that the initial balances must be positive.
            //BankAccount invalidAccount;
            //try
            //{
            //    invalidAccount = new BankAccount("invalid", -55);
            //}
            //catch (ArgumentOutOfRangeException e)
            //{
            //    Console.WriteLine("Exception caught creating account with negative balance");
            //    Console.WriteLine(e.ToString());
            //    return;
            //}


        }
    }
}

三.结果

Hello World!
Account 1234567890 was created for <name> with 1000 initial balance.
500
600
Date            Amount  Balance Note
2022/11/11      1000    1000    Initial balance
2022/11/11      -500    500     Rent payment
2022/11/11      100     600     Friend paid me back

Account 1234567891 was created for lianhua with 1040 initial balance.
Date            Amount  Balance Note
2022/11/11      1040    1040    Initial balance

_______________________________________
Account 1234567892 was created for gift card with 100 initial balance.
Date            Amount  Balance Note
2022/11/11      100     100     Initial balance
2022/11/11      -20     80      get expensive coffee
2022/11/11      -50     30      buy groceries
2022/11/11      50      80      Add monthly deposit
2022/11/11      27.50   107.50  add some additional spending money

Account 1234567893 was created for savings account with 10000 initial balance.
Date            Amount  Balance Note
2022/11/11      10000   10000   Initial balance
2022/11/11      750     10750   save some money
2022/11/11      1250    12000   Add more savings
2022/11/11      -250    11750   Needed to pay monthly bills
2022/11/11      587.50  12337.50        apply monthly interest

____________________________
Account 1234567894 was created for line of credit with 0 initial balance.
Account 1234567895 was created for line of credit with 0 initial balance.
Date            Amount  Balance Note
2022/11/11      -1000   -1000   Take out monthly advance
2022/11/11      50      -950    Pay back small amount
2022/11/11      -5000   -5950   Emergency funds for repairs
2022/11/11      -20     -5970   Apply overdraft fee
2022/11/11      150     -5820   Partial restoration on repairs


C:\...\net6.0\PracticeBasic.exe (process 9104) exited with code 0.
Press any key to close this window . . .

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值