{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "a29ab6d8",
   "metadata": {},
   "source": [
    "```{index} class; instance examples\n",
    "```\n",
    "\n",
    "(class-instance-examples)=\n",
    "\n",
    "# Class Instance\n",
    "\n",
    "```{index} exercise; getters and setters\n",
    "```\n",
    "\n",
    "(more-getters-and-setters)=\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7e2ed2ea",
   "metadata": {},
   "source": "## More Getters and Setters\n\nAs an exercise you could write a simple class Example, with\n\n1. `int` instance variable `n` and `double` instance variable `d`\n2. a simple constructor with parameters to set instance variables\n   `n` and `d`\n3. getters and setters for both instance variables (4 methods in all)\n4. a ToString that prints a line with both instance variables labeled.\n\nCompare yours to\n[example_class/example_class.cs](https://github.com/mstbit/introcs-csharp-examples/blob/master/example_class/example_class.cs).\n\nWe include a testing class at the end of this file.\n\n```{literalinclude} ../../examples/example_class/example_class.cs\n:start-after: test class\n```\n\nBesides the obvious tests, we also use\nthe fact that an Example object is mutable to play with {ref}`alias`:\nIn the\nlast few lines of `Main`, after `e` becomes an alias for `e2`,\nwe change\nan object under one name, and it affect the alias the same way.\nCheck this by running the program!\n\nMake sure you can follow the code and the output from running.\n\n```{index} Averager Example\n```\n\n(beyond-getters-and-setters)=\n\n```{rubric} Beyond Getters and Setters\n```\n\nThus far we have had very simple classes with instance variables and\ngetter and setter methods, and maybe a ToString method.\nThese classes were designed to introduce the basic syntax for\nclasses with instances. The classes have just been containers for data\nthat we can read back, and change if there are setter methods - pretty\nboring and limited. Many objects have more extensive behaviors, so we will\ntake a small step and imagine a somewhat more complicated `Averager` class:\n\n- A new `Averager` starts with no data acknowledged.\n- Be able to enter data values one at a time (method `AddDatum`).\n  We will use `double` values.\n- At any point be able to return the average of the numbers entered so far\n  (method `GetAverage`).\n  The average is the sum of all the values divided by number of values.\n  With `double` values we assume a `double` average.\n  This does not make sense if there\n  are no values so far, but with double type we can use the value\n  `NaN` (Not a Number) in this case.\n- Be able to return the number of data elements entered so far\n  (method `GetDataCount`)\n- Be able to clear the `Averager`, going back to no data elements\n  considered yet, like in a new `Averager` (method `Clear`)\n- It is good to have a `ToString` method. We choose to have\n  it label the number of data items and the average of the items.\n\nThe object starts from a fixed\nstate (no data) so we do not need any constructor parameters.\n\nWe can imagine a demonstration class `AveragerDemo` with a `Main` method\ncontaining\n\n```{literalinclude} ../../examples/averager/averager_demo.cs\n:end-before: chunk\n:start-after: chunk\n```\n\nIt should print\n\n```none\nNew Averager: items: 0; average: NaN\nNext datum 5.1\naverage 5.1 with 1 data values\nNext datum -7.3\naverage -1.1 with 2 data values\nNext datum 11\naverage 2.93333333333333 with 3 data values\nNext datum 3.7\naverage 3.125 with 4 data values\nAfter clearing:\naverage NaN with 0 data values\n```\n\nNow that we have a clear idea of the proposed outward behavior, we\ncan consider how to implement the `Averager` class.\n\nWe could store a list of all the data values entered in any instance,\nrequiring a large amount of memory for a long list. However, this\nfunctionality was built into early calculators, with very limited memory.\nHow can we do it without remembering the whole list?\nConsider a concrete example:\n\nIf I have entered numbers 2.1, 4.5 and 5.4, and want the average, it is\n\n> $(2.1+4.5+5.4)/3=12.0/3=4.0$\n\nIf I want to include a further number 5.0, the average becomes\n\n> $(2.1+4.5+5.4+5.0)/4=17.0/4=4.25$\n\nNote the relationship to the previous average expression:\n\n> $=((2.1+4.5+5.4)+5.0)/4=(12.0+5.0)/(3+1)$\n\nIn the numerator we have added the latest value to the previous sum,\nand in the denominator the count of data items is increased by one.\nAll we need to remember to\ngo on to include the next item is the sum of values so far and the\nnumber of values so far. We can just have instance variables\n`sum` and `dataCount`.\n\nYou might think how to create this class....\n\nThe full `Averager` code follows:\n\n```{literalinclude} ../../examples/averager/averager.cs\n```\n\nSeveral things to note:\n\n- We show that a constructor, like an instance method, can include a call\n  to a further instance method. Though we illustrate this idea, the\n  constructor code is\n  actually unneeded. See the {ref}`unneeded-constructor-code-exercise` below.\n- We have methods that are not ToString or mere getters or setters of instance\n  variables. The logic of the class requires more.\n- The `GetAverage`\n  method does return data obtained by reading instance variable, but it does\n  a calculation using the instance variables first. See\n  {ref}`alternate-internal-state-exercise`.\n\nThe code for both classes is in project [averager](https://github.com/mstbit/introcs-csharp-examples/tree/master/averager)."
  },
  {
   "cell_type": "markdown",
   "id": "c07b2b71",
   "metadata": {},
   "source": "## Statistics Exercise\n\nModify the project [averager](https://github.com/mstbit/introcs-csharp-examples/tree/master/averager) so the `Averager` class is\nconverted to `Statistics`. Besides having methods to calculate the count\nof data items and average, also calculate the standard deviation with\na method `StandardDeviation`.\nIt turns out that the only other instance variable needed is\nthe sum of the squares of the data items, call it `sumOfSqr`.\nBefore calculating the standard deviation, suppose we\nassign the current average to a local variable `avg`.\nThen the handiest form of expression for the standard deviation is\n\n```\nMath.Sqrt((sumOfSqr - avg*avg)/dataCount)\n```\n\nModify the demonstration program to show the standard deviation, too."
  },
  {
   "cell_type": "markdown",
   "id": "808f4468",
   "metadata": {},
   "source": "(unneeded-constructor-code-exercise)=\n\n## Unneeded Constructor Code Exercise\n\nRecall that objects are always initialized. Each instance variable\nhas a default value assigned before a constructor is even run.\nThe default value for numeric instance variables is 0, so the\ncall to `Clear` in the constructor could be left out, leaving the\nbody of the constructor empty! Try commenting that line out\nand test that the behavior of demo program is the same.\n\nEmphasizing the fact that you are thinking about the\ninitial values of instance variables is not a bad idea. Hence\na common practice is to\nexplicitly assign even the default values in the constructor, as\nwe did initially with the call to `Clear` inside the constructor.\n\nIf no constructor definition is explicitly provided at all,\nthe compiler implicitly creates one with no parameters and an empty body.\nThis means that the entire constructor in `Averager` could be omitted.\nComment the whole constructor out and check.\n\nThere is a defensive programming\nreason to provide even the do-nothing constructor explicitly:\nIf you use the implicit constructor and then decide to add a constructor\nwith parameters, the implicit constructor is no longer defined by the compiler,\nso any remaining call to it in your code becomes an error."
  },
  {
   "cell_type": "markdown",
   "id": "82dc22b2",
   "metadata": {},
   "source": "(alternate-internal-state-exercise)=\n\n## Alternate Internal State Exercise\n\nThe way we represent the internal state for an `Averager` is the\nbest probably, but if it turns out that the `GetAverage` method\nis called a lot more often than a method that changes the state,\nwe could avoid repeated division by saving the average as an\ninstance variable. We could keep that *instead of* `sum`\n(and still keep `dataCount`). We can manage to\nkeep the same public interface to the methods. With these\nalternate instance variables how would you change\nthe implementation code and not change the method headings or meanings?\nIf we keep the assumption that the average of 0\nitems is\n`double.Nan`, you will need to treat adding the first datum as\na special case. The code is simpler if we change the outward assumptions\nenough to consider the average of 0 items\nto be 0. Try it either way.\n\nIn the version with NaN you can avoid testing for NaN,\nbut if you choose to test for\nNaN, you need the boolean `Double.IsNaN` function, because the expression\n`double.NaN == double.NaN` is *false*!"
  },
  {
   "cell_type": "markdown",
   "id": "footnotes",
   "metadata": {},
   "source": "```{rubric} Footnotes\n```\n"
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": ".NET (C#)",
   "language": "C#",
   "name": ".net-csharp"
  },
  "language_info": {
   "name": "csharp"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}