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

Previous

\n", "

Next

\n", "

Tour of Scala

\n", "
\n", "\n", "# Compound Types\n", "\n", "Sometimes it is necessary to express that the type of an object is a subtype of several other types. In Scala this can be expressed with the help of *compound types*, which are intersections of object types.\n", "\n", "Suppose we have two traits `Cloneable` and `Resetable`:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "attributes": { "classes": [ "tut" ], "id": "" } }, "outputs": [ { "data": { "text/plain": [ "defined \u001b[32mtrait\u001b[39m \u001b[36mCloneable\u001b[39m\n", "defined \u001b[32mtrait\u001b[39m \u001b[36mResetable\u001b[39m" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "trait Cloneable extends java.lang.Cloneable {\n", " override def clone(): Cloneable = {\n", " super.clone().asInstanceOf[Cloneable]\n", " }\n", "}\n", "trait Resetable {\n", " def reset: Unit\n", "}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now suppose we want to write a function `cloneAndReset` which takes an object, clones it and resets the original object:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```scala\n", "def cloneAndReset(obj: ?): Cloneable = {\n", " val cloned = obj.clone()\n", " obj.reset\n", " cloned\n", "}\n", "```\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The question arises what the type of the parameter `obj` is. If it's `Cloneable` then the object can be `clone`d, but not `reset`; if it's `Resetable` we can `reset` it, but there is no `clone` operation. To avoid type casts in such a situation, we can specify the type of `obj` to be both `Cloneable` and `Resetable`. This compound type is written like this in Scala: `Cloneable with Resetable`.\n", "\n", "Here's the updated function:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```scala\n", "def cloneAndReset(obj: Cloneable with Resetable): Cloneable = {\n", " //...\n", "}\n", "```\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Compound types can consist of several object types and they may have a single refinement which can be used to narrow the signature of existing object members.\n", "The general form is: `A with B with C ... { refinement }`\n", "\n", "An example for the use of refinements is given on the page about [class composition with mixins](mixin-class-composition.ipynb).\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 }