{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "df922049-690d-4afa-b3a4-395bf465d1ba",
   "metadata": {},
   "source": "```{index} class; Rational Rational class\n```\n\n(rational)=\n\n# Operator Overloading\n\n**This section is for your further learning/exercise and the Rational class is referenced\nby other sections**\n\nLike other numbers, we think of a rational number as a unit,\nbut all rational numbers can be most easily represented as a fraction,\na ratio of two integers. We can create a class Rational, so\n\n    Rational r = new Rational(2, 3);\n\nwould create a new Rational number for the mathematical expression, 2/3.\n\nOur previous simple class examples have mostly been ways of\ncollecting related data, with limited methods beyond getters and setters.\nRational numbers also have lots of obvious operations defined on them.\nOur Rational example we will use most of the concepts for object so far,\nand add a few more, to provide a rich practical class\nwith a variety of methods.\n\nThinking ahead to what we would like for our rational numbers, here is\nsome testing code. Hopefully the method names are clear and reasonable.\nin the illustration\nwe operate on a single rational number, and do calculation with a pair,\nand parse string literals. The code is from\n[test_rational/test_rational.cs](https://github.com/mstbit/introcs-csharp-examples/blob/master/test_rational/test_rational.cs):\n\n```{literalinclude} ../../examples/test_rational/test_rational.cs\n```\n\nOne non-obvious method is `CompareTo`. This one method allows\nall the usual comparison operators to be used with the result.\nWe will discuss it more in {ref}`rationals-revisited`.\n\nThe results we would like when running this testing code:\n\n``` none\n6/(-10) simplifies to -3/5\nreciprocal of -3/5 is -5/3\n-3/5 negated is 3/5\n-3/5 + 1/2 is -1/10\n-3/5 - 1/2 is -11/10\n-3/5 * 1/2 is -3/10\n(-3/5) / (1/2) is -6/5\n1/2 > -3/5 ? true\n-3/5 as a double is -0.6\n1/2 as a decimal is 0.5\nParse \"-12/30\" to Rational: -2/5\nParse \"123\" to Rational: 123\nParse \"1.125\" to Rational: 9/8\n```\n\nA Rational has a numerator and a denominator. We must remember that data.\nEach individual Rational that we use will have its own numerator and\ndenominator, which we store as the instance variables\n(and which we abbreviate since we are lazy):\n\n    public class Rational\n    {\n       private int num;\n       private int denom;\n       // ...\n\nWe could have a very simple constructor that just copies in values for\nthe numerator and denominator. However, there is an extra wrinkle with\nrational numbers: They can be represented many ways. You remember from\ngrade school being told to “reduce to lowest terms”. This will keep\nour internal representations unique, and use the smallest numbers.\n\nIntermediate operations and initial constructor parameters\nwill not always be in lowest terms. To reduce to lowest terms\nwe need to divide the original numerator and denominator by their\n{ref}`gcd`. We include a *static* GCD method taken from that section,\nand make the adjustment to lowest terms in a helping method, `Normalize`,\nthat is called by the constructor:\n\n```{index} private; helping method\n```\n\n```{literalinclude} ../../examples/rational_nunit/rational.cs\n:end-before: chunk\n:start-after: normalize chunk\n```\n\nThere are several things to note about this method:\n\n- It is *private*.\n  It is only used as a helping method, called from inside of Rational. It\n  is not a part of the public interface used from other classes.\n- We need to deal with a 0 denominator somehow. We should be causing an\n  *exception*, but that is an advanced topic, so we wimp out and just\n  change the denominator to 1.\n- There is one other technical issue in getting a unique representation: The\n  denominator could start off being negative.\n  If that is the case, we change the sign of\n  both the numerator and denominator, so we always end up with a positive\n  denominator. We will use this fact in several places.\n- It calls a static method of the class, `GCD`. Classes can have both\n  instance and static methods. It is fine for an instance method like\n  `Normalize` to call a static method: The instance variables cannot be\n  accessed. Here `GCD` is passed all its data explicitly through\n  its parameters.\n\nThe complete constructor, using `Normalize`, is below.\nNote that by the time we\nare done constructing a new Rational, it is in this normalized form: lowest\nterms and positive denominator:\n\n```{literalinclude} ../../examples/rational_nunit/rational.cs\n:end-before: chunk\n:start-after: constructor chunk\n```\n\nThe call to the `Normalize` method is another place where we have a\ncall without dot notation, since it\nis acting on the same object as for the constructor.\n\nWe mentioned that instance method `Normalize` calls static method `GCD`,\nand this is fine. The reverse is not true:\n\nInside a `static` method there\nis *no* current object. A common compiler error is caused when you\ntry to have a static method call\nan instance method without dot notation for a specific object.\nThe shorthand notation\nwithout an explicit object reference and dot cannot be used, because\nthere is no\ncurrent object to reference implicitly:\n\n    public void AnInstanceMethod()\n    {\n          ...\n    }\n\n    public static void AStaticMethod()  // no current object\n    {\n           AnInstanceMethod();  // COMPILER ERROR CAUSED\n    }\n\nOn the other hand, there is no issue when\nan instance method calls a static method. (The instance variables are just\ninaccessible inside the static method.)\n\nThe Rational class has the usual getter methods, to access the\nobvious parts of its state:\n\n```{literalinclude} ../../examples/rational_nunit/rational.cs\n:end-before: chunk\n:start-after: getter chunk\n```\n\nWe certainly want to be able to display a Rational as a string version:\n\n```{literalinclude} ../../examples/rational_nunit/rational.cs\n:end-before: chunk\n:start-after: ToString chunk\n```\n\nNote that we simplify so you would see “3” rather than “3/1”. This is also\na place where the normalization to have a positive denominator comes in:\na negative Rational will always have a leading “-” as in “-5/9” rather than\n“5/-9”\n\nWith a Rational, several other conversions make sense: to `double`\nand `decimal` approximations.\n\n```{literalinclude} ../../examples/rational_nunit/rational.cs\n:end-before: chunk\n:start-after: ToDouble chunk\n```\n\nSo far we have returned built-in types. What if we wanted to generate\nthe reciprocal of a Rational? That would be another Rational. It is\nlegal to return the type of the class that you are defining!\nHow do we make a new Rational?\nWe have a constructor! We can easily use it. The reciprocal\nswaps the numerator and denominator. It is also easy to negate\na Rational:\n\n```{literalinclude} ../../examples/rational_nunit/rational.cs\n:end-before: chunk\n:start-after: Reciprocal chunk\n```\n\nStatic methods are still useful.\nFor example, in analogy with the other numeric types\nwe may want a static `Parse` method\nto act on a string parameter and return a new Rational.\n\nThe most obvious kind of string to parse would be one like `\"2/3\"` or `\"-10/77\"`,\nwhich we can split at the `'/'`.\nIntegers are also rational numbers, so we would like to parse `\"123\"`.\nFinally decimal strings can be converted to rational numbers,\nso we would like to parse `\"123.45\"`.\n\nSee how our `Parse` method below distinguishes and handles\nall the cases. It constructs integer strings,\n`parts[0]` and `parts[1]`, for both the numerator and denominator,\nand then parses the integers. Note that the method *is* `static`.\nThere is no Rational\nbeing referred to when it starts, but in this case the method *returns* one.\n\nThat last case is the trickiest. For example `\"123.45\"` becomes 12345/100\n(before being reduced to lowest terms).\nNote that there were originally *two* digits after the decimal point\nand then the denominator gets *two* zeroes to have the right power of 10:\n\n```{literalinclude} ../../examples/rational_nunit/rational.cs\n:end-before: chunk\n:start-after: Parse chunk\n```\n\n"
  },
  {
   "cell_type": "markdown",
   "id": "0d176bcd",
   "metadata": {},
   "source": [
    "(rationals-revisited)=\n\n## Method Parameters of the Same Type\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2f193764",
   "metadata": {},
   "source": [
    "(defining_operators)=\n",
    "\n",
    "## Operator Definitions\n",
    "\n",
    "We can deal with the current object without using dot notation. What if we are\n",
    "dealing with *more than one* Rational, the current one *and* another one,\n",
    "like the parameter in Multiply:\n",
    "\n",
    "```{literalinclude} ../../examples/rational_nunit/rational.cs\n",
    ":end-before: chunk\n",
    ":start-after: Multiply chunk\n",
    "```\n",
    "\n",
    "We can mix the shorthand notation for the current object’s fields\n",
    "and dot notation for another\n",
    "*named* object: `num` and `denom` refer to the fields in the *current* object, and\n",
    "`f.num` and `f.denom` refer to fields for the other\n",
    "`Rational`, the parameter `f`.\n",
    "\n",
    "```{literalinclude} ../../examples/rational_nunit/rational.cs\n",
    ":end-before: Divide chunk\n",
    ":start-after: Multiply chunk\n",
    "```\n",
    "\n",
    "We do not refer to the fields of `f` through the public methods\n",
    "`GetNumerator` and `GetDenominator`.\n",
    "Though `f` is not the same *object*, it is the same *type*:\n",
    "\n",
    "Private members of *another* object of the *same* type are\n",
    "accessible from method definitions in the class.\n",
    "\n",
    "There are a number of other arithmetic methods in the source code for Rational\n",
    "that return a new Rational result of the arithmetic operation. They *do* review\n",
    "your knowledge of arithmetic! They do *not* add further C# syntax.\n",
    "\n",
    "The whole code for Rational is in [rational_nunit/rational.cs](https://github.com/mstbit/introcs-csharp-examples/blob/master/rational_nunit/rational.cs).\n",
    "The testing code we started with, in\n",
    "[test_rational/test_rational.cs](https://github.com/mstbit/introcs-csharp-examples/blob/master/test_rational/test_rational.cs)\n",
    "uses all the methods. We will see more advance ways to test Rational\n",
    "in {ref}`unit-testing`.\n",
    "\n",
    "There is also a more convenient version of Rational,\n",
    "using advanced concepts, in {ref}`defining_operators`.\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b5f9e8c6",
   "metadata": {},
   "source": "## Pictorial Playing Computer\n\nLet us start pictorially playing computer on {file}`test_rational.cs`,\nas a review of much of the previous sections. We explicitly show a local variable\n`this` to identify the current object in an instance method or constructor.\n\nThe first line of `Main`,\n\n    Rational f = new Rational(6, -10);\n\ncreates a new Rational, so it calls the constructor. At the very beginning of the\nconstructor, a prototype `Rational` is already created as the current object,\nso immediately, there is a `this`.\nThe parameters 6, and -10 are passed, initializing the explicit local\nvariables `numerator` and `denominator`.\nThe figure illustrates the memory state at the beginning of the constructor call:\n\n`{image} ../../images/callConstructor.png :width: 124 pt`\n\nNote the immediate value assigned to the numeric instance variables is zero: This is\nas discussed in {ref}`default-fields`.\nOf course we do not want to keep those default values:\nThe constructor finds the value of the local variable `numerator`, and needs to\nassign the value 6 to a variable `num`. The compiler has looked\nfirst for a local variable `num`, and found none.\nThen it looked *second* for an instance variable in the object pointed to\nby `this`. It found `num` there. Now it copies the 6 into that location.\nSimilarly for `denominator` and `denom`:\n\n`{image} ../../images/callConstructorCopied.png :width: 124 pt`\n\nThen the constructor calls `Normalize`.\nSince `Normalize` is also an instance method,\na reference to `this` is passed implicitly.\nWhile illustrating the memory state for more than one active method,\nwe separate each one with a horizontal segment.\n\n`{image} ../../images/callNormalize.png :width: 124 pt`\n\nLater `Normalize` calls `GCD`. Since `GCD` is static, note that the local\nvariables for `GCD` do *not* contain a reference to `this`.\n\n`{image} ../../images/callGCD.png :width: 124 pt`\n\nAt the end of `GCD` the `int` 2 is returned and initializes\n`n` in the calling method `Normalize`.\nThen `Normalize` modifies the instance variable pointed to by `this`,\nand finishes.\n\n`{image} ../../images/finishNormalize.png :width: 124 pt`\n\nThat is the same object `this` in the constructor.\nJust before the constructor completes we have:\n\n`{image} ../../images/finishConstructor.png :width: 124 pt`\n\nThen in `Main` the constructor’s `this` is the reference to the new object\ninitializing `f`.\n\n`{image} ../../images/setF.png :width: 120 pt`\n\nConsider the next line of `Main`:\n\n    Console.WriteLine(\"6/(-10) simplifies to {0}\", f);\n\nWe omit the internals of the WriteLine call, except to note that it must convert\nthe reference `f` to a string. As with any object,\nit does this by calling the `ToString` method for `f`,\nso the implicit `this` in the call to `ToString` refers to the same object as `f`:\n\n`{image} ../../images/callToString.png :width: 196.5 pt`\n\n`ToString` returns “-3/5”, and it gets printed as part of the line generated\nby `WriteLine`….\n\nWe skip the similar details through two more `WriteLine` statements and the\ninitialization of `h`:\n\n    Rational h = new Rational(1,2);\n\nThe `WriteLine`\nstatement after that needs to evaluate `f.Add(h)`, generating a call to `Add`.\nThe next figure shows the two local variables in `Main`, `f` and `h`, each\npointing to a `Rational` object. The image shows the situation\nin the call to `Add`, just before the end of the return statement,\nwhen the new Rational is being constructed.\n\nIn the local variables for the method `Add`\nsee what the implicit `this` refers to, and what the\n(local to `Add`) variable `f` refer to. As the figure shows,\nthis use of a local variable\n`f` is independent of the `f` in `Main`:\n\n`{image} ../../images/callAdd.png :width: 132 pt`\n\nSince the return statement in `Add` creates a new object,\nthe figure shows a call to the\nconstructor from inside `Add`. We do not go through the details of another\nconstructor call, but\n`this` in the constructor points to the Rational shown and returned by\n`Add`:\n\n`{image} ../../images/endAdd.png :width: 132 pt`\n\nwhich gets sent to the `WriteLine` statement\nand gets printed in `Main` as in the earlier code.\n\nMake sure you see how the pictures reinforce these important ideas:\n\n- Keeping track of the `this` with\n  constructors and instance methods (but not static methods).\n- The aliasing of `Rational` objects used as parameters explicitly or\n  implicitly (`this`).\n\nWe have played computer before in procedural programming,\nfollowing individually explicitly named\nvariables. This has allowed us to follow loops clearly after the code is\nwritten. The pictorial version with multiple object references and method calls\nis also useful for checking on code that is written with many object\nreferences.\n\nWhen first *writing* code with object references that you are manipulating,\na picture of the setup\nshowing the references in your data is also helpful.\nNew object-oriented programmers often have a hard time referring to the\ndata they want to work with.\nIf you have a picture of the data relationships\nyou can point with a finger to a part that you want to use.\nFor example\nin the call to `Add`, one piece of data you need for your arithmetic is\nthe `num` field in `f`. Then you must be carful to note\nthat *only local variables can be referenced directly*\n(including the implicit `this`). If you want to refer to data that is not a local\nvariable, you must follow the reference path arrow that leads *from a local variable* to\nan instance field that you want to reference.\n\n`{image} ../../images/pathToNum.png :width: 132 pt`\n\nThen use the proper object-oriented notation to refer to the path.\nIn the example, it takes one step,\nfrom local variable `f` to its field `num`, referred to as `f.num`.\nSimilarly the current object’s `num` is connected through `this`, but C# shorthand\nallows `this.` to be omitted. And so on, for `f.denom` and `denom`.\n\nVisually following such paths will be even more important later, when we construct\nmore complex types of objects, and you need to follow\na path through *several* references in sequence.\n\n```{index} exercise; ForceMatch\n```"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": "public struct SomeMath\n{\n   // ...\n}\n",
   "id": "63594661"
  },
  {
   "cell_type": "markdown",
   "id": "29990790",
   "metadata": {},
   "source": "\nSo why the distinction? We have mentioned that new objects created in a class are\naccessed indirectly via a reference, as with an array. As a general category,\nthey are called *reference objects*. We distinguished the types `int` and\n`double` and `bool`, where the actual value of the data is stored in the space\nfor a variable of the type. They are *value types*. A struct is also a value\ntype. In practice this is efficient for small objects of a fixed size.\nWe made Rational a class because\nyou have already seen the class construct with\n`static` entries, and classes are more generally useful.\nIn fact being a `struct` would be a good choice for Rational,\nsince it only contains two integers. Its size is no more than one `double`.\n\nThe behavior of a Rational is the same either way, because it is immutable. If we\nallowed mutating methods, then a class version and a struct version would not behave\nthe same way, due to the fact the reference types can have aliases,\nand value types cannot.\n\nThere are some more complicated situations where there are further distinctions between\nclasses and structs, but we shall not concern ourselves\nwith those fine advanced points in this book."
  },
  {
   "cell_type": "markdown",
   "id": "7248e473-6fc1-491e-a327-5cf0eb96654d",
   "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
}