{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "

Previous

\n", "

Next

\n", "

Tour of Scala

\n", "
\n", "\n", "# Upper Type Bounds\n", "\n", "In Scala, [type parameters](generic-classes.ipynb) and [abstract types](abstract-types.ipynb) may be constrained by a type bound. Such type bounds limit the concrete values of the type variables and possibly reveal more information about the members of such types. An _upper type bound_ `T <: A` declares that type variable `T` refers to a subtype of type `A`.\n", "Here is an example that demonstrates upper type bound for a type parameter of class `PetContainer`:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "attributes": { "classes": [ "tut" ], "id": "" } }, "outputs": [ { "data": { "text/plain": [ "defined \u001b[32mclass\u001b[39m \u001b[36mAnimal\u001b[39m\n", "defined \u001b[32mclass\u001b[39m \u001b[36mPet\u001b[39m\n", "defined \u001b[32mclass\u001b[39m \u001b[36mCat\u001b[39m\n", "defined \u001b[32mclass\u001b[39m \u001b[36mDog\u001b[39m\n", "defined \u001b[32mclass\u001b[39m \u001b[36mLion\u001b[39m\n", "defined \u001b[32mclass\u001b[39m \u001b[36mPetContainer\u001b[39m\n", "\u001b[36mdogContainer\u001b[39m: \u001b[32mPetContainer\u001b[39m[\u001b[32mDog\u001b[39m] = ammonite.$sess.cmd0$Helper$PetContainer@5ce7ef5d\n", "\u001b[36mcatContainer\u001b[39m: \u001b[32mPetContainer\u001b[39m[\u001b[32mCat\u001b[39m] = ammonite.$sess.cmd0$Helper$PetContainer@5caf67b8" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "abstract class Animal {\n", " def name: String\n", "}\n", "\n", "abstract class Pet extends Animal {}\n", "\n", "class Cat extends Pet {\n", " override def name: String = \"Cat\"\n", "}\n", "\n", "class Dog extends Pet {\n", " override def name: String = \"Dog\"\n", "}\n", "\n", "class Lion extends Animal {\n", " override def name: String = \"Lion\"\n", "}\n", "\n", "class PetContainer[P <: Pet](p: P) {\n", " def pet: P = p\n", "}\n", "\n", "val dogContainer = new PetContainer[Dog](new Dog)\n", "val catContainer = new PetContainer[Cat](new Cat)" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "attributes": { "classes": [ "tut" ], "id": "" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "cmd1.sc:104: type arguments [cmd1.this.cmd0.Lion] do not conform to class PetContainer's type parameter bounds [P <: Helper.this.Pet]\n", "val lionContainer = new PetContainer[Lion](new Lion)\n", " ^cmd1.sc:1: type arguments [cmd1.this.cmd0.Lion] do not conform to class PetContainer's type parameter bounds [P <: Helper.this.Pet]\n", "val lionContainer = new PetContainer[Lion](new Lion)\n", " ^cmd1.sc:8: type arguments [cmd1.this.cmd0.Lion] do not conform to class PetContainer's type parameter bounds [P <: Helper.this.Pet]\n", " .print(lionContainer, \"lionContainer\", _root_.scala.None)\n", " ^cmd1.sc:8: type arguments [cmd1.this.cmd0.Lion] do not conform to class PetContainer's type parameter bounds [P <: Helper.this.Pet]\n", " .print(lionContainer, \"lionContainer\", _root_.scala.None)\n", " ^Compilation Failed" ] }, { "ename": "", "evalue": "", "output_type": "error", "traceback": [ "Compilation Failed" ] } ], "source": [ "// this would not compile\n", "val lionContainer = new PetContainer[Lion](new Lion)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The `class PetContainer` take a type parameter `P` which must be a subtype of `Pet`. `Dog` and `Cat` are subtypes of `Pet` so we can create a new `PetContainer[Dog]` and `PetContainer[Cat]`. However, if we tried to create a `PetContainer[Lion]`, we would get the following Error:\n", "\n", "`type arguments [Lion] do not conform to class PetContainer's type parameter bounds [P <: Pet]`\n", "\n", "This is because `Lion` is not a subtype of `Pet`.\n", "

Previous

\n", "

Next

\n", "

Tour of Scala

\n", "
" ] } ], "metadata": { "kernelspec": { "display_name": "Scala (2.13)", "language": "scala", "name": "scala213" }, "language_info": { "codemirror_mode": "text/x-scala", "file_extension": ".scala", "mimetype": "text/x-scala", "name": "scala", "nbconvert_exporter": "script", "version": "2.13.1" } }, "nbformat": 4, "nbformat_minor": 4 }