{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "6c09dc35",
   "metadata": {},
   "source": [
    "# Lab 19: Classes\n",
    "\n",
    "In this lab, you'll get practice creating and using objects for existing classes as well as add functionality to a class."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "72767501",
   "metadata": {},
   "source": [
    "### Rectangle class\n",
    "Consider the following `Rectangle` class from the lecture along with the code that creates two different rectangles and uses them for a simple calculation."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "1d8debea",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The larger rectangle has dimensions 100 by 50\n"
     ]
    }
   ],
   "source": [
    "class Rectangle:\n",
    "    \"\"\"\n",
    "    Used for representing rectangles\n",
    "    \n",
    "    attributes: length, width\n",
    "    \"\"\"\n",
    "    def __init__(self, starting_length, starting_width):\n",
    "        self.length = starting_length\n",
    "        self.width = starting_width\n",
    "        \n",
    "    def area(self):\n",
    "        return self.length*self.width\n",
    "    \n",
    "    def perimeter(self):\n",
    "        return 2*self.length + 2*self.width\n",
    "    \n",
    "def main():\n",
    "    r1 = Rectangle(100,50) #r1 is a Rectangle object\n",
    "    r2 = Rectangle(10,20) #r2 is a Rectangle objecct\n",
    "\n",
    "    if r1.area() > r2.area():\n",
    "        print(\"The larger rectangle has dimensions\",r1.length,\"by\",r1.width)\n",
    "    else:\n",
    "        print(\"The larger rectangle has dimensions\",r2.length,\"by\",r2.width)\n",
    "\n",
    "main()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "30dcf740",
   "metadata": {},
   "source": [
    "__Exercise 1:__ Change the code so that both the length and width of one of the rectanges is 25. _Hint:_ you shouldn't need to change any code in the `Rectangle` class - just the code that instantiates `Rectangle` objects."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d1f6c393",
   "metadata": {},
   "source": [
    "__Exercise 2:__ Write some code that creates three new rectangles with different dimensions. Again, you shouldn't need to change the code in the `Rectangle` class, and you shouldn't need to define a _new_ class - create three new Rectangle objects that are all from the same original class."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dde8c089",
   "metadata": {},
   "source": [
    "__Exercise 3:__ Create a `Cuboid` class for representing three-dimensional objects with a length, width, and height. Examples of real-world cuboids are things like six-sided dice, bricks, etc. Come up with at least two methods that would be useful for a `Cuboid` to have."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3b544eeb",
   "metadata": {},
   "source": [
    "__Exercise 4:__ Create two `Cuboid` objects and practice calling their methods."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "09a71439",
   "metadata": {},
   "source": [
    "### BankAccount class\n",
    "\n",
    "Consider the following `BankAccount` class from the lecture."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "eb0a4570",
   "metadata": {},
   "outputs": [],
   "source": [
    "class BankAccount:\n",
    "    \"\"\"\n",
    "    A class for creating objects representing bank accounts\n",
    "    \n",
    "    attributes:\n",
    "        balance - amount of money in the account\n",
    "        customer_name - the customer's name\n",
    "        interest_rate - interest rate for the account\n",
    "    \"\"\"\n",
    "    def __init__(self, starting_customer_name):\n",
    "        self.customer_name = starting_customer_name\n",
    "        self.__balance = 0\n",
    "        self.interest_rate = 0.0\n",
    "        \n",
    "    def deposit(self, amount):\n",
    "        if amount > 0:\n",
    "            self.__balance += amount\n",
    "        else:\n",
    "            print(\"Error: the deposit amount must be positive.\")\n",
    "    \n",
    "    def apply_interest(self):\n",
    "        self._balance = self.__balance * (1+self.interest_rate)\n",
    "        \n",
    "    def display_info(self):\n",
    "        print(\"Account Holder:\",self.customer_name)\n",
    "        print(\"Balance:\",self.__balance)\n",
    "        print(\"Interest Rate:\",self.interest_rate)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ec97d090",
   "metadata": {},
   "source": [
    "__Exercise 5:__ Create a program that does the following:\n",
    "* ask the user their name and an initial deposit amount\n",
    "* create a BankAccount object for them, and call the `deposit()` method for the initial deposit\n",
    "* display their account information with the `display_info()` method\n",
    "\n",
    "_Hint:_ You should not need to change the code inside the class at all - you're just creating objects of this class."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cae0938d",
   "metadata": {},
   "source": [
    "__Exercise 6:__ Add a new `withdraw()` method to the `BankAccount` class that allows for money to be subtracted from the account's balance. Make sure to give an error if they try to withdraw more money than is in the account."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f5e38fec",
   "metadata": {},
   "source": [
    "__Challenge Exercise 7:__ Write a program that uses the BankAccount class in some way - maybe it's a menu that lets users interact with a bank account - presenting options for opening, depositing, or withdrawing from their account. Or, maybe you have another idea for how to use this class - anything is fine as long as it creates a BankAccount object and calls your `withdraw()` method at least once. You're also welcome to add additional attributes and methods that might be useful for your program (though you are not required to). When you are finished, submit your code to the __Lab 19: BankAccount class__ assignment on codePost (there is no automated testing of this one)."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
