{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "d3e02879",
   "metadata": {},
   "source": [
    "# Encapsulation\n",
    "\n",
    "Encapsulation is the practice of bundling data and the operations that work on it into a single unit (the class),\n",
    "while hiding internal details from the outside world. You have already been applying this in the Classes chapter —\n",
    "private fields, properties, and constructors are all encapsulation in action. Here we name it formally and\n",
    "examine *why* it matters as a design principle.\n",
    "\n",
    "In C#, encapsulation is achieved by:\n",
    "\n",
    "- declaring fields as `private` so external code cannot access them directly\n",
    "- exposing controlled access through `public` properties (`get` / `set`)\n",
    "- using methods to enforce rules about how state can change\n",
    "\n",
    "There are two main ways to implement encapsulation in C#:\n",
    "\n",
    "- Using properties\n",
    "- Using methods\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ca50bc3e",
   "metadata": {},
   "source": [
    "## Using Properties\n",
    "\n",
    "Properties are a special type of class member that provide a way to read and\n",
    "write the value of a private field. They allow you to control access to the\n",
    "field while still providing a simple and convenient way to access its value.\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "017af822",
   "metadata": {
    "language_info": {
     "name": "polyglot-notebook"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    }
   },
   "outputs": [],
   "source": [
    "namespace IntroCSCS {\n",
    "    public class BankAccount\n",
    "    {\n",
    "        private decimal balance;\n",
    "\n",
    "        public decimal Balance              // Balance property; a special method with\n",
    "        {                                   // getter and setter\n",
    "            get { return balance; }\n",
    "            set { balance = value; }\n",
    "        }\n",
    "    }\n",
    "\n",
    "    class Program{\n",
    "        // Can access balance through the Balance property\n",
    "        BankAccount account = new BankAccount();\n",
    "        account.Balance = 100;\n",
    "        Console.WriteLine(account.Balance);\n",
    "    }\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "866d847a",
   "metadata": {},
   "source": [
    "(instance-methods)=\n",
    "\n",
    "## Using methods\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "936de637",
   "metadata": {},
   "source": [
    "\n",
    "You can implement encapsulation by using methods to access and modify the values\n",
    "of private fields. This allows you to control access to the fields and enforce\n",
    "any necessary business logic or validation.\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "90d72ca3",
   "metadata": {
    "language_info": {
     "name": "polyglot-notebook"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    }
   },
   "outputs": [],
   "source": [
    "namespace IntroCSCS {\n",
    "    public class BankAccount\n",
    "    {\n",
    "        private decimal balance;                        // private field\n",
    "\n",
    "        public BankAccount(decimal initialBalance)      // constructor; set default value\n",
    "        {\n",
    "            balance = initialBalance;\n",
    "        }\n",
    "\n",
    "        public decimal GetBalance()                     // using method to implement encapsulation.\n",
    "        {\n",
    "            return balance;\n",
    "        }\n",
    "\n",
    "        public void Deposit(decimal amount)\n",
    "        {\n",
    "            balance += amount;\n",
    "        }\n",
    "\n",
    "        public void Withdraw(decimal amount)\n",
    "        {\n",
    "            balance -= amount;\n",
    "        }\n",
    "    }\n",
    "\n",
    "    class Program {\n",
    "        static void Main(string[] args)\n",
    "        {\n",
    "            BankAccount myAccount = new BankAccount(1000);\n",
    "\n",
    "            myAccount.Deposit(500);\n",
    "            Console.WriteLine(\"Balance: \" + myAccount.GetBalance());\n",
    "                                                                // output: balance: 1500\n",
    "            myAccount.Withdraw(2000);\n",
    "            Console.WriteLine(\"Balance: \" + myAccount.GetBalance());\n",
    "        }                                                       // Balance: -500\n",
    "    }\n",
    "}\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "73941172",
   "metadata": {},
   "source": [
    "\n",
    "Let us take a look at this class:\n",
    "\n",
    "- **Security**: You interact with the BankAccount object through its public methods, never\n",
    "  directly accessing the balance field.\n",
    "- **The \\`\\`BankAccount\\`\\` class**: The `BankAccount` class **encapsulates** data\n",
    "  (the `balance` field) and related operations (the `Deposit` and `Withdraw` methods).\n",
    "- **The balance field**: The balance field is marked as **private**, meaning it can\n",
    "  only be accessed within the BankAccount class. This ensures that the balance can\n",
    "  only be `modified` through the Deposit and Withdraw methods, which can enforce\n",
    "  any necessary business logic or validation.\n",
    "- **The GetBalance method**: The GetBalance method, on the other hand, is marked as\n",
    "  public, meaning it can be called from outside the BankAccount class. This allows\n",
    "  other code to retrieve the balance without being able to modify it directly.\n",
    "\n",
    "Take a look at another example. In the program below, the class Student is encapsulated\n",
    "as the variables are declared as private. To access these private variables we\n",
    "are using the `Name` and `Age` `accessors` which contain the get and set method\n",
    "to retrieve and set the values of private fields. Accessors are defined as public\n",
    "so that they can access in other class.\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3b592af9",
   "metadata": {
    "language_info": {
     "name": "polyglot-notebook"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    }
   },
   "outputs": [],
   "source": [
    "namespace IntroCSCS\n",
    "{\n",
    "    public class Student\n",
    "    {\n",
    "        private String studentName;     // private variables declared\n",
    "        private int studentAge;         // these can only be accessed by public getter/setter\n",
    "\n",
    "        public String Name              // Property; getter/setter accessors\n",
    "        {\n",
    "            get { return studentName; }\n",
    "            set { studentName = value; }\n",
    "        }\n",
    "\n",
    "        public int Age                  // getter/setter accessors to access Age\n",
    "        {\n",
    "            get { return studentAge; }\n",
    "            set { studentAge = value; }\n",
    "        }\n",
    "    }\n",
    "\n",
    "\n",
    "    class Program\n",
    "    {\n",
    "        static void Main(string[] args)\n",
    "        {\n",
    "\n",
    "            Student obj = new Student();\n",
    "            obj.Name = \"TY Chen\";           // set field value\n",
    "            obj.Age = 35;                   // set field value\n",
    "\n",
    "            Console.WriteLine(\" Name : \" + obj.Name);   // output: Name : TY Chen\n",
    "            Console.WriteLine(\" Age : \" + obj.Age);     // output: Age : 35\n",
    "        }\n",
    "    }\n",
    "}\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "footnotes",
   "metadata": {},
   "source": [
    "```{rubric} Footnotes\n",
    "```\n"
   ]
  }
 ],
 "metadata": {
  "jupytext": {
   "cell_metadata_filter": "-all",
   "main_language": "python",
   "notebook_metadata_filter": "-all"
  },
  "kernelspec": {
   "display_name": ".NET (C#)",
   "language": "C#",
   "name": ".net-csharp"
  },
  "language_info": {
   "name": "polyglot-notebook"
  },
  "polyglot_notebook": {
   "kernelInfo": {
    "defaultKernelName": "csharp",
    "items": [
     {
      "aliases": [],
      "name": "csharp"
     }
    ]
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
