Deprecated: Creation of dynamic property wpdb::$categories is deprecated in /var/www/twodee/blog/wp-includes/wp-db.php on line 668

Deprecated: Creation of dynamic property wpdb::$post2cat is deprecated in /var/www/twodee/blog/wp-includes/wp-db.php on line 668

Deprecated: Creation of dynamic property wpdb::$link2cat is deprecated in /var/www/twodee/blog/wp-includes/wp-db.php on line 668

Deprecated: Return type of WP_Theme::offsetExists($offset) should either be compatible with ArrayAccess::offsetExists(mixed $offset): bool, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-theme.php on line 554

Deprecated: Return type of WP_Theme::offsetGet($offset) should either be compatible with ArrayAccess::offsetGet(mixed $offset): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-theme.php on line 595

Deprecated: Return type of WP_Theme::offsetSet($offset, $value) should either be compatible with ArrayAccess::offsetSet(mixed $offset, mixed $value): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-theme.php on line 535

Deprecated: Return type of WP_Theme::offsetUnset($offset) should either be compatible with ArrayAccess::offsetUnset(mixed $offset): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-theme.php on line 544

Deprecated: Return type of WP_REST_Request::offsetExists($offset) should either be compatible with ArrayAccess::offsetExists(mixed $offset): bool, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/rest-api/class-wp-rest-request.php on line 960

Deprecated: Return type of WP_REST_Request::offsetGet($offset) should either be compatible with ArrayAccess::offsetGet(mixed $offset): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/rest-api/class-wp-rest-request.php on line 980

Deprecated: Return type of WP_REST_Request::offsetSet($offset, $value) should either be compatible with ArrayAccess::offsetSet(mixed $offset, mixed $value): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/rest-api/class-wp-rest-request.php on line 992

Deprecated: Return type of WP_REST_Request::offsetUnset($offset) should either be compatible with ArrayAccess::offsetUnset(mixed $offset): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/rest-api/class-wp-rest-request.php on line 1003

Deprecated: Return type of WP_Block_List::current() should either be compatible with Iterator::current(): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 151

Deprecated: Return type of WP_Block_List::next() should either be compatible with Iterator::next(): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 175

Deprecated: Return type of WP_Block_List::key() should either be compatible with Iterator::key(): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 164

Deprecated: Return type of WP_Block_List::valid() should either be compatible with Iterator::valid(): bool, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 186

Deprecated: Return type of WP_Block_List::rewind() should either be compatible with Iterator::rewind(): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 138

Deprecated: Return type of WP_Block_List::offsetExists($index) should either be compatible with ArrayAccess::offsetExists(mixed $offset): bool, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 75

Deprecated: Return type of WP_Block_List::offsetGet($index) should either be compatible with ArrayAccess::offsetGet(mixed $offset): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 89

Deprecated: Return type of WP_Block_List::offsetSet($index, $value) should either be compatible with ArrayAccess::offsetSet(mixed $offset, mixed $value): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 110

Deprecated: Return type of WP_Block_List::offsetUnset($index) should either be compatible with ArrayAccess::offsetUnset(mixed $offset): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 127

Deprecated: Return type of WP_Block_List::count() should either be compatible with Countable::count(): int, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 199

Deprecated: Creation of dynamic property Automattic\Jetpack\Connection\Manager::$error_handler is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/vendor/automattic/jetpack-connection/src/class-manager.php on line 91

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Instagram_Gallery::$is_wpcom is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-instagram-gallery.php on line 23

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Mailchimp::$wpcom_is_wpcom_only_endpoint is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-mailchimp.php on line 17

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Tweetstorm_Gather::$wpcom_is_wpcom_only_endpoint is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-tweetstorm-gather.php on line 21

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Tweetstorm_Gather::$is_wpcom is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-tweetstorm-gather.php on line 22

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Gutenberg_Available_Extensions::$wpcom_is_site_specific_endpoint is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/gutenberg-available-extensions.php on line 20

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Memberships::$wpcom_is_wpcom_only_endpoint is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/memberships.php on line 23

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Memberships::$wpcom_is_site_specific_endpoint is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/memberships.php on line 24

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Subscribers::$wpcom_is_wpcom_only_endpoint is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/subscribers.php on line 15

Deprecated: Creation of dynamic property Automattic\Jetpack\Sync\Queue::$random_int is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/vendor/automattic/jetpack-sync/src/class-queue.php on line 38

Deprecated: Creation of dynamic property Automattic\Jetpack\Sync\Queue::$random_int is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/vendor/automattic/jetpack-sync/src/class-queue.php on line 38

Deprecated: Creation of dynamic property WPCOM_Widget_Goodreads::$shelves is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/modules/widgets/goodreads.php on line 33

Deprecated: DateTime::__construct(): Passing null to parameter #1 ($datetime) of type string is deprecated in /var/www/twodee/blog/wp-includes/script-loader.php on line 348

Deprecated: Creation of dynamic property Advanced_Editor_Tools::$toolbar_classic_block is deprecated in /var/www/twodee/blog/wp-content/plugins/tinymce-advanced/tinymce-advanced.php on line 347

Deprecated: Creation of dynamic property Advanced_Editor_Tools::$toolbar_block is deprecated in /var/www/twodee/blog/wp-content/plugins/tinymce-advanced/tinymce-advanced.php on line 349

Deprecated: Creation of dynamic property Advanced_Editor_Tools::$toolbar_block_side is deprecated in /var/www/twodee/blog/wp-content/plugins/tinymce-advanced/tinymce-advanced.php on line 350

Deprecated: Creation of dynamic property Advanced_Editor_Tools::$panels_block is deprecated in /var/www/twodee/blog/wp-content/plugins/tinymce-advanced/tinymce-advanced.php on line 351

Deprecated: Creation of dynamic property Advanced_Editor_Tools::$used_block_buttons is deprecated in /var/www/twodee/blog/wp-content/plugins/tinymce-advanced/tinymce-advanced.php on line 354

Deprecated: Creation of dynamic property WP_Block_Type::$plan_check is deprecated in /var/www/twodee/blog/wp-includes/class-wp-block-type.php on line 333

Deprecated: Creation of dynamic property WP_Block_Type::$plan_check is deprecated in /var/www/twodee/blog/wp-includes/class-wp-block-type.php on line 333

Deprecated: Creation of dynamic property WP_Block_Type::$plan_check is deprecated in /var/www/twodee/blog/wp-includes/class-wp-block-type.php on line 333

Deprecated: Creation of dynamic property WP_Block_Type::$plan_check is deprecated in /var/www/twodee/blog/wp-includes/class-wp-block-type.php on line 333

Deprecated: Creation of dynamic property WP_Block_Type::$plan_check is deprecated in /var/www/twodee/blog/wp-includes/class-wp-block-type.php on line 333

Deprecated: Creation of dynamic property WP_Block_Type::$plan_check is deprecated in /var/www/twodee/blog/wp-includes/class-wp-block-type.php on line 333

Deprecated: Creation of dynamic property WP_Term::$object_id is deprecated in /var/www/twodee/blog/wp-includes/class-wp-term.php on line 198

Deprecated: Creation of dynamic property WP_Term::$object_id is deprecated in /var/www/twodee/blog/wp-includes/class-wp-term.php on line 198

Deprecated: Creation of dynamic property WP_Term::$object_id is deprecated in /var/www/twodee/blog/wp-includes/class-wp-term.php on line 198
» CS 330: Lecture 16 – Ad Hoc Polymorphism Continued

teaching machines

CS 330: Lecture 16 – Ad Hoc Polymorphism Continued

March 9, 2018 by . Filed under
Deprecated: Creation of dynamic property WP_Term::$cat_ID is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 378

Deprecated: Creation of dynamic property WP_Term::$category_count is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 379

Deprecated: Creation of dynamic property WP_Term::$category_description is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 380

Deprecated: Creation of dynamic property WP_Term::$cat_name is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 381

Deprecated: Creation of dynamic property WP_Term::$category_nicename is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 382

Deprecated: Creation of dynamic property WP_Term::$category_parent is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 383

Deprecated: Creation of dynamic property WP_Term::$cat_ID is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 378

Deprecated: Creation of dynamic property WP_Term::$category_count is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 379

Deprecated: Creation of dynamic property WP_Term::$category_description is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 380

Deprecated: Creation of dynamic property WP_Term::$cat_name is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 381

Deprecated: Creation of dynamic property WP_Term::$category_nicename is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 382

Deprecated: Creation of dynamic property WP_Term::$category_parent is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 383

Deprecated: Creation of dynamic property WP_Term::$cat_ID is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 378

Deprecated: Creation of dynamic property WP_Term::$category_count is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 379

Deprecated: Creation of dynamic property WP_Term::$category_description is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 380

Deprecated: Creation of dynamic property WP_Term::$cat_name is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 381

Deprecated: Creation of dynamic property WP_Term::$category_nicename is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 382

Deprecated: Creation of dynamic property WP_Term::$category_parent is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 383
cs330, lectures, spring 2018.

Dear students,

As we discussed last time, polymorphism is the pursuit of code that works with many types. It manifests itself in several forms that we’ve been discussing:

We started discussing ad hoc polymorphism last time, and we overloaded operator[] for our super fast string class. It made our string feel a lot like an array. Or does it? What happens here?

Zing z = "goliath";
z[0] = 'G';

To make the character writable, we can return a reference instead of a temporary:

char &operator[](int i) {
  return text[i];
}

It’s common practice in C++ to provide two versions of methods, one that returns a reference and another that is const and returns a plain old value.

Now suppose we want to print the whole string just like we can print other things in C++:

std::cout << z << std::endl;

What do we want to overload here? A method of cout? The rules of C++ state that the compiler will look first for something like this:

ostream &ostream::operator<<(const Zing &z);

But there’s no way we can sneak into the ostream class and an overloaded definition for our new class. However, if this method can’t be found, the compiler then looks for a method like this:

ostream &operator<<(ostream &stream, const Zing &z);

The difference here is that operator<< is not owned by any class. It’s a top-level definition. We can write it like so:

std::ostream &operator<<(std::ostream &stream, const Zing &z) {
  for (int i = 0; i < z.Length(); ++i) {
    stream << z[i];
  }
  return stream;
}

Overloading functions still requires us to write a version for each different type we want to support, which is probably why it’s called “ad hoc”—which is Latin for “for this.” You write a version for this type, and for this other type, and for this even more other type… But from the client perspective, there’s just one function.

How does overloading work in Javascript? Or Ruby? Let’s check. Here’s a hypot method that supports either two or three dimensions:

function hypot(a, b, c) {
  return Math.sqrt(a * a + b * b + c * c);
}

function hypot(a, b) {
  return Math.sqrt(a * a + b * b);
}

console.log(hypot(3, 4));
console.log(hypot(1, 4, 8));

Does this give the output we expect? Not at all. Because Javascript doesn’t support function overloading. Nor does Ruby. Nor does Python. The name is bound to only a single definition. Which one? Whichever definition appeared last.

In these languages, we have a few options to emulate overloading. We can combine the multiple definitions into an if-ladder and inspect the parameters to arbitrate between them. In Javascript, we can examine the length of the implicit arguments array:

function hypot(a, b, c) {
  if (arguments.length == 3) {
    return Math.sqrt(a * a + b * b + c * c);
  } else {
    return Math.sqrt(a * a + b * b);
  }
}

console.log(hypot(3, 4));
console.log(hypot(1, 4, 8));

Or we could inquire directly about c, which takes on the magic value of undefined if the caller doesn’t provide an actual parameter:

function hypot(a, b, c) {
  if (c !== undefined) {
    return Math.sqrt(a * a + b * b + c * c);
  } else {
    return Math.sqrt(a * a + b * b);
  }
}

console.log(hypot(3, 4));
console.log(hypot(1, 4, 8));

Our other option is to try and generalize the code so that one definition serves all types. In the case of hypot, we can make it work with just two dimensions by forcing c to be 0. But instead of relying on the caller to do that, we provide a default parameter:

function hypot(a, b, c=0) {
  return Math.sqrt(a * a + b * b + c * c);
}

console.log(hypot(3, 4));
console.log(hypot(1, 4, 8));

Neither of these approaches is overloading, but it makes us feel like overloading is supported.

Let’s try this out in pure C:

#include <math.h>

double hypot(double a, double b) {
  return sqrt(a * a + b * b);
}

double hypot(double a, double b, double c) {
  return sqrt(a * a + b * b + c * c);
}

We find that this code doesn’t even compile. There are some hacks to emulate it as we did in Javascript, but they go against the grain of the language.

Overloading is a nice feature to have, I think. In a sense, it ascribes an identity on a function that is a compound primary key: its name plus its parameters. Languages without overloading use a much simpler primary key: the name alone. When we get to Haskell, we’ll take this idea of overloading even further and provide different definitions of a function differentiated not just by parameter type, but by parameter value.

There we have it. Two different means of making our functions handle several different types. And neither has to do with inheritance! Next we’ll talk about subtype polymorphism.

To experiment with subtype polymorphism in C++, we’re going to create a terminal-based graphing calculator. Plotting in the terminal sounds a little awkward, and it is. But it’ll be fun. We’ll use the Ncurses library to position the cursor at arbitrary locations on the screen. Here’s a first step, which plots just the x- and y-axes.

#include <ncurses.h>

class Calculator {
  public:
    Calculator() {
      initscr();
      clear();
      getmaxyx(stdscr, height, width);
    }

    void plot() {
      int mid_x = width / 2;
      int mid_y = height / 2;

      for (int x = 0; x < width; ++x) {
        mvprintw(mid_y, x, ".");
      }

      for (int y = 0; y < height; ++y) {
        mvprintw(y, mid_x, ".");
      }

      getch();
      endwin();
    }

  private:
    int width;
    int height;
};

Here’s a main method to get it up and running. Eventually we’ll feed it some functions, but not today.

int main(int argc, char **argv) {
  Calculator calc;
  calc.plot();
  return 0;
}

Here’s your TODO list for next time:

See you then!

Sincerely,

P.S. Here’s the code we wrote together:

zing.cpp

#include <iostream>

using std::ostream;

#define FOO 6

class Zing {
  public:
    Zing(const char *source) {
      length = strlen(source);
      s = new char[length];
      memcpy(s, source, length);
    }

    char operator[](int i) const {
      return s[i];
    }

    char &operator[](int i) {
      return s[i];
    }

    ~Zing() {
      delete[] s;
    }

    int LeNgTh() const {
      return length;
    }

  private:
    char *s;
    int length;
};

ostream &operator<<(ostream &stream, const Zing &z) {
  for (int i = 0; i < z.LeNgTh(); ++i) {
    stream << z[i];
  }
  return stream;
}

int main(int argc, char **argv) {
  Zing z = "Jordan's Sister";
  std::cout << "z: " << z << std::endl;
  z[0] = 'G';
  std::cout << "z: " << z << std::endl;
  /* operator<<(operator<<(operator<<(cout, "z: "), z), endl); */

  return 0;
}

hypot.js

// function hypot(a, b) {
  // return Math.sqrt(a * a + b * b);
// }

function hypot(a, b, c) {
  // if (c === undefined) {
  if (arguments.length == 2) {
    return Math.sqrt(a * a + b * b);
  } else {
    return Math.sqrt(a * a + b * b + c * c);
  }
}

function hypot(a, b, c=0) {
  var sum = 0;
  arguments.forEach(arg -> sum += arg * arg);
  return Math.sqrt(sum);
  // return Math.sqrt(a * a + b * b + c * c);
}

console.log("hypot(3, 4):", hypot(3, 4, null)); // 5
console.log("hypot(1, 4, 8):", hypot(1, 4, 8)); // 9

Calc.cpp

#include <iostream>

#include <ncurses.h>

class Calc {
  public:
    Calc() {
      initscr();
      clear();
      getmaxyx(stdscr, height, width);
    }

    void plot() {
      getch();
      endwin();
    }

  private:
    int width;
    int height;
};

int main(int argc, char **argv) {
  Calc c; 
  c.plot();
  return 0;
}