Shape Abstractions
DataMatrix Generation In NoneUsing Barcode generation for Font Control to generate, create Data Matrix 2d barcode image in Font applications.
www.OnBarcode.com Draw GTIN - 12 In NoneUsing Barcode printer for Font Control to generate, create UPC-A Supplement 2 image in Font applications.
www.OnBarcode.com If we have a collection of shapes that derive from the common trait OShape that has an area method on it, our object definitions would look something like the following if we used a traditional OOP approach:
Creating Data Matrix In NoneUsing Barcode creation for Font Control to generate, create DataMatrix image in Font applications.
www.OnBarcode.com Encode Code 39 Extended In NoneUsing Barcode maker for Font Control to generate, create Code39 image in Font applications.
www.OnBarcode.com trait OShape { def area: Double } class OCircle(radius: Double) extends OShape { def area = radius * radius * Math.Pi } class OSquare(length: Double) extends OShape { def area = length * length } class ORectangle(h: Double, w: Double) extends OShape { def area = h * w }
Painting Barcode In NoneUsing Barcode maker for Font Control to generate, create Barcode image in Font applications.
www.OnBarcode.com Printing Barcode In NoneUsing Barcode creator for Font Control to generate, create Barcode image in Font applications.
www.OnBarcode.com Let s compare this with the pattern-matching implementation:
GS1-128 Creation In NoneUsing Barcode drawer for Font Control to generate, create GS1 128 image in Font applications.
www.OnBarcode.com Make Code11 In NoneUsing Barcode creation for Font Control to generate, create Code 11 image in Font applications.
www.OnBarcode.com trait Shape case class Circle(radius: Double) extends Shape case class Square(length: Double) extends Shape case class Rectangle(h: Double, w: Double) extends Shape object Shape { def area(shape: Shape): Double = shape match { case Circle(r) => r * r * Math.Pi case Square(l) => l * l case Rectangle(h, w) => h * w } }
Data Matrix 2d Barcode Creator In NoneUsing Barcode generation for Microsoft Word Control to generate, create ECC200 image in Office Word applications.
www.OnBarcode.com DataMatrix Maker In JavaUsing Barcode printer for BIRT Control to generate, create ECC200 image in BIRT applications.
www.OnBarcode.com CHAPTER 5 PATTERN MATCHING
Print USS Code 128 In JavaUsing Barcode encoder for Android Control to generate, create Code 128 Code Set C image in Android applications.
www.OnBarcode.com UPC-A Supplement 2 Drawer In C#Using Barcode maker for Visual Studio .NET Control to generate, create UPC-A image in .NET framework applications.
www.OnBarcode.com In the pattern-matching example, all of the logic for calculating area is located in the same method, but the fact that the method exists is not obvious from looking at the Shape trait. So far, the OOP methodology seems to be the right answer because it makes obvious what shapes can do. However, if we have a shape library and we want to calculate the perimeter of each of the shapes, there s a benefit to pattern matching:
Printing GTIN - 13 In NoneUsing Barcode encoder for Online Control to generate, create EAN-13 image in Online applications.
www.OnBarcode.com UCC - 12 Encoder In JavaUsing Barcode drawer for Java Control to generate, create UPC Code image in Java applications.
www.OnBarcode.com def perimeter(shape: Shape) = shape match { case Circle(r) => 2 * Math.Pi * r case Square(l) => 4 * l case Rectangle(h, w) => h * 2 + w * 2 }
Creating Barcode In .NETUsing Barcode drawer for .NET Control to generate, create Barcode image in Visual Studio .NET applications.
www.OnBarcode.com Encode Barcode In NoneUsing Barcode maker for Office Excel Control to generate, create Barcode image in Microsoft Excel applications.
www.OnBarcode.com In this case, the open data makes implementing the perimeter method possible. With the OOP implementation, we would have to expose data to make the perimeter method possible to implement. So our OOP implementation would look like
QR Code ISO/IEC18004 Creation In Objective-CUsing Barcode generator for iPad Control to generate, create Quick Response Code image in iPad applications.
www.OnBarcode.com Code 39 Full ASCII Reader In Visual C#Using Barcode decoder for .NET Control to read, scan read, scan image in .NET framework applications.
www.OnBarcode.com trait OShape { def area: Double } class def def } class def def } class def def def } OCircle(radius: Double) extends OShape { area = radius * radius * Math.Pi getRadius = radius OSquare(length: Double) extends OShape { area = length * length getLength = length ORectangle(h: Double, w: Double) extends OShape { area = h * w getHeight = h getWidth = w
Printing GS1 - 13 In NoneUsing Barcode creator for Office Word Control to generate, create UPC - 13 image in Word applications.
www.OnBarcode.com Making Data Matrix In JavaUsing Barcode creator for Java Control to generate, create Data Matrix ECC200 image in Java applications.
www.OnBarcode.com More broadly, it s rare that the designer of an object hierarchy implements all the methods that a library consumer is going to need. The visitor pattern is a design pattern that allows you to add functionality to a class hierarchy after the hierarchy is already defined. Let s look at a typical visitor pattern implementation. Following is the interface that defines the visitor. The code contains
CHAPTER 5 PATTERN MATCHING
circular class references and will not work at the REPL. So, first the code, and then a walkthrough of the code:
trait def def def def } OCarVisitor { visit(wheel: OWheel): Unit visit(engine: OEngine): Unit visit(body: OBody): Unit visit(car: OCar): Unit
trait OCarElement { def accept(visitor: OCarVisitor): Unit } class OWheel(val name: String) extends OCarElement { def accept(visitor: OCarVisitor) = visitor.visit(this) } class OEngine extends OCarElement { def accept(visitor: OCarVisitor) = visitor.visit(this) } class OBody extends OCarElement { def accept(visitor: OCarVisitor) = visitor.visit(this) } class OCar extends OCarElement { val elements = List(new OEngine, new OBody, new OWheel("FR"), new OWheel("FL"), new OWheel("RR"), new OWheel("RL")) def accept(visitor: OCarVisitor) = (this :: elements).foreach(_.accept(visitor)) }
The library author has to think about extensibility and implement the visitor pattern. Note also that the class hierarchy is fixed in the visitor because the visitor has to implement an interface that defines all the possible classes that the visitor can handle:
trait def def def def } OCarVisitor { visit(wheel: OWheel): Unit visit(engine: OEngine): Unit visit(body: OBody): Unit visit(car: OCar): Unit