family polymorphism 590p seminar february 16, 2005
TRANSCRIPT
![Page 1: Family Polymorphism 590P Seminar February 16, 2005](https://reader036.vdocuments.mx/reader036/viewer/2022062423/56649ef25503460f94c04534/html5/thumbnails/1.jpg)
Family Polymorphism
590P Seminar
February 16, 2005
![Page 2: Family Polymorphism 590P Seminar February 16, 2005](https://reader036.vdocuments.mx/reader036/viewer/2022062423/56649ef25503460f94c04534/html5/thumbnails/2.jpg)
Traditional polymorphism Let x refer to an object of class C {C1,C2,
…,Cn}, where each Ci provides (or inherits) a method m()
Call site x.m() provides safety: Type checking can ensure that x has an m(). Late-binding ensures correct m() invoked.
Also provides reuse: x can refer to any Ci
![Page 3: Family Polymorphism 590P Seminar February 16, 2005](https://reader036.vdocuments.mx/reader036/viewer/2022062423/56649ef25503460f94c04534/html5/thumbnails/3.jpg)
What is family polymorphism? A family describes a set of related classes. Given a set of families providing a common
interface: {{A1,B1,C1},…,{An,Bn,Cn}} If m() is a method provided by all A’s and
taking an argument of class B, we want reuse: x.m(y) works for any Ai and Bi
Also want safety: Ai and Bi must be from the same family
![Page 4: Family Polymorphism 590P Seminar February 16, 2005](https://reader036.vdocuments.mx/reader036/viewer/2022062423/56649ef25503460f94c04534/html5/thumbnails/4.jpg)
Motivation Traditional OOP allows variability at the level
of a single class. Paper argues that modern software
engineering requires support for variability on a larger scale.
Argue that popularity of aspect-oriented programming demonstrates need for multi-class variability.
Examples??
![Page 5: Family Polymorphism 590P Seminar February 16, 2005](https://reader036.vdocuments.mx/reader036/viewer/2022062423/56649ef25503460f94c04534/html5/thumbnails/5.jpg)
Example: Graphs Two mutually recursive classes Edge
and Node. An Edge has two Nodes. A Node has a method touches(Edge e) that returns true if the edge e touches the node.
![Page 6: Family Polymorphism 590P Seminar February 16, 2005](https://reader036.vdocuments.mx/reader036/viewer/2022062423/56649ef25503460f94c04534/html5/thumbnails/6.jpg)
Extending Graph An OnOffGraph:
OnOffEdge has an extra field enabled OnOffNode.touches(e) only returns
true if e is enabled. Can extend in other ways as well:
Colored graphs Labelled graphs
![Page 7: Family Polymorphism 590P Seminar February 16, 2005](https://reader036.vdocuments.mx/reader036/viewer/2022062423/56649ef25503460f94c04534/html5/thumbnails/7.jpg)
Safety and Reusability Reuse:
Want to write methods that can work with either Edges and Nodes, or with OnOffEdges and OnOffNodes.
Safety: The methods should not allow mixing–e.g.,
attaching an OnOffEdge to a Node. Exisiting approaches can provide reuse or
safety, but not both.
![Page 8: Family Polymorphism 590P Seminar February 16, 2005](https://reader036.vdocuments.mx/reader036/viewer/2022062423/56649ef25503460f94c04534/html5/thumbnails/8.jpg)
Reuse via subtyping
class Node { boolean touches(Edge e) { return (this==e.n1) || (this==e.n2); }}
class Edge { Node n1, n2;}
![Page 9: Family Polymorphism 590P Seminar February 16, 2005](https://reader036.vdocuments.mx/reader036/viewer/2022062423/56649ef25503460f94c04534/html5/thumbnails/9.jpg)
Reuse via subtyping
class OnOffNode extends Node { boolean touches(Edge e) { return ((OnOffEdge)e).enabled? super.touches(e) : false; }}
class OnOffEdge extends Edge { boolean enabled; OnOffEdge() { this.enabled=false; }}
![Page 10: Family Polymorphism 590P Seminar February 16, 2005](https://reader036.vdocuments.mx/reader036/viewer/2022062423/56649ef25503460f94c04534/html5/thumbnails/10.jpg)
Reuse via subtypingpublic class Main { static void build(Node n,Edge e,boolean b){ e.n1=e.n2=n; if (b == n.touches(e)) System.out.println(“OK”); } public static void main(String[] args) { build(new Node(), new Edge(), true); build(new OnOffNode(), new OnOffEdge(), false); }}
![Page 11: Family Polymorphism 590P Seminar February 16, 2005](https://reader036.vdocuments.mx/reader036/viewer/2022062423/56649ef25503460f94c04534/html5/thumbnails/11.jpg)
Why is this unsafe?public class Main { static void build(Node n,Edge e,boolean b){ e.n1=e.n2=n; if (b == n.touches(e)) System.out.println(“OK”); } public static void main(String[] args) { build(new Node(), new Edge(), true); build(new OnOffNode(), new OnOffEdge(), false); build(new OnOffNode(), new Edge(), true); }}
![Page 12: Family Polymorphism 590P Seminar February 16, 2005](https://reader036.vdocuments.mx/reader036/viewer/2022062423/56649ef25503460f94c04534/html5/thumbnails/12.jpg)
Runtime Error!
public static void main(String[] args) { build(new Node(), new Edge(), true); build(new OnOffNode(), new OnOffEdge(), false); build(new OnOffNode(), new Edge(), true); }
class OnOffNode extends Node { boolean touches(Edge e) { return ((OnOffEdge)e).enabled? ...
![Page 13: Family Polymorphism 590P Seminar February 16, 2005](https://reader036.vdocuments.mx/reader036/viewer/2022062423/56649ef25503460f94c04534/html5/thumbnails/13.jpg)
Another unsafe call
This “works” (i.e., no errors, prints OK). But not the intended semantics.
Nodes should be used with Edges, not OnOffEdges.
Node::touches() ignores enabled field
build(new Node(), new OnOffEdge(), true);
![Page 14: Family Polymorphism 590P Seminar February 16, 2005](https://reader036.vdocuments.mx/reader036/viewer/2022062423/56649ef25503460f94c04534/html5/thumbnails/14.jpg)
Try again, with templates
template <class N,class E> struct NodeF;template <class N,class E> struct EdgeF { N *n1,*n2; };template <class N,class E> struct NodeF { virtual bool touches(E* e) { return (this==e->n1) || (this==e->n2); }
struct Edge;struct Node: public NodeF<Node,Edge> {};struct Edge: public EdgeF<Node,Edge> {};
![Page 15: Family Polymorphism 590P Seminar February 16, 2005](https://reader036.vdocuments.mx/reader036/viewer/2022062423/56649ef25503460f94c04534/html5/thumbnails/15.jpg)
On-off graphs
template <class ON,class OE>struct OnOffEdgeF: public EdgeF<ON,OE> { bool enabled; OnOffEdgeF(): enabled(false) {} };template <class ON,class OE>struct OnOffNodeF: public NodeF<ON,OE> { bool touches(OE* e) { return e->enabled ? NodeF<ON,OE>::touches(e) : false; }};
![Page 16: Family Polymorphism 590P Seminar February 16, 2005](https://reader036.vdocuments.mx/reader036/viewer/2022062423/56649ef25503460f94c04534/html5/thumbnails/16.jpg)
On-off graphs, cont…
struct OnOffEdge;struct OnOffNode : public OnOffNodeF<OnOffNode,OnOffEdge> {};struct OnOffEdge : public OnOffEdgeF<OnOffNode,OnOffEdge> {};
![Page 17: Family Polymorphism 590P Seminar February 16, 2005](https://reader036.vdocuments.mx/reader036/viewer/2022062423/56649ef25503460f94c04534/html5/thumbnails/17.jpg)
But no reuse …
void build1(Node* n, Edge* e, bool b) { e->n1=e->n2=n; if (b == n->touches(e)) cout << “OK\n”;}
void build2(OnOffNode *n,OnOffEdge *e,bool b){ e->n1=e->n2=n; if (b == n->touches(e)) cout << “OK\n”;}
OnOffNode not a subtype of Node
![Page 18: Family Polymorphism 590P Seminar February 16, 2005](https://reader036.vdocuments.mx/reader036/viewer/2022062423/56649ef25503460f94c04534/html5/thumbnails/18.jpg)
A templated build()? Could get reuse by templating the
arguments to build. Problems with this approach:
Types must be known statically at call site. When we pass a node to a template
function, every function it passes through in the call chain must be templated.
Can’t create data structures containing nodes and edges belonging together.
![Page 19: Family Polymorphism 590P Seminar February 16, 2005](https://reader036.vdocuments.mx/reader036/viewer/2022062423/56649ef25503460f94c04534/html5/thumbnails/19.jpg)
Reuse and Safety via Virtual Types Virtual types allow types to be attributes
of objects. Thus, we can make an object that acts
as a “repository of types”. These “repositories” can store our
families. We’ll show how this works with gbeta -
beta with support for families.
![Page 20: Family Polymorphism 590P Seminar February 16, 2005](https://reader036.vdocuments.mx/reader036/viewer/2022062423/56649ef25503460f94c04534/html5/thumbnails/20.jpg)
Graphs in gbetaGraph: (# Node:< (# touches:< (# e:^Edge; b:@boolean enter e[] do(this(Node)=e.n1 or this(Node)=e.n2)->b exit b #); exit this(Node)[] #); Edge:< (# n1,n2:^Node exit this(Edge)[] #) #);
![Page 21: Family Polymorphism 590P Seminar February 16, 2005](https://reader036.vdocuments.mx/reader036/viewer/2022062423/56649ef25503460f94c04534/html5/thumbnails/21.jpg)
On-off graphs in gbeta
OnOffGraph: Graph (# Node::< (# touches::<!(# do (if e.enabled then INNER if) #) #) Edge::< (# enabled: @boolean #)#);
![Page 22: Family Polymorphism 590P Seminar February 16, 2005](https://reader036.vdocuments.mx/reader036/viewer/2022062423/56649ef25503460f94c04534/html5/thumbnails/22.jpg)
build() in gbeta
build: (# g:<@Graph; n:^g.Node; e:^g.Edge; b:@boolean enter (n[],e[],b) do n->e.n1[]->e.n2[]; (if (e->n.touches)=b then ‘OK’->putline if)#);g1:@Graph; g2:@OnOffGraph
![Page 23: Family Polymorphism 590P Seminar February 16, 2005](https://reader036.vdocuments.mx/reader036/viewer/2022062423/56649ef25503460f94c04534/html5/thumbnails/23.jpg)
build() in gbeta
build: (# g:<@Graph; n:^g.Node; e:^g.Edge; b:@boolean enter (n[],e[],b) do n->e.n1[]->e.n2[]; (if (e->n.touches)=b then ‘OK’->putline if)#);g1:@Graph; g2:@OnOffGraph
(g1.Node, g1.Edge, true) -> build(#g::@g1#);
![Page 24: Family Polymorphism 590P Seminar February 16, 2005](https://reader036.vdocuments.mx/reader036/viewer/2022062423/56649ef25503460f94c04534/html5/thumbnails/24.jpg)
build() in gbeta
build: (# g:<@Graph; n:^g.Node; e:^g.Edge; b:@boolean enter (n[],e[],b) do n->e.n1[]->e.n2[]; (if (e->n.touches)=b then ‘OK’->putline if)#);g1:@Graph; g2:@OnOffGraph
(g2.Node, g2.Edge, false) -> build(#g::@g2#);
![Page 25: Family Polymorphism 590P Seminar February 16, 2005](https://reader036.vdocuments.mx/reader036/viewer/2022062423/56649ef25503460f94c04534/html5/thumbnails/25.jpg)
build() in gbeta
build: (# g:<@Graph; n:^g.Node; e:^g.Edge; b:@boolean enter (n[],e[],b) do n->e.n1[]->e.n2[]; (if (e->n.touches)=b then ‘OK’->putline if)#);g1:@Graph; g2:@OnOffGraph
(g2.Node, g1.Edge, false) -> build(#g::@g2#);
![Page 26: Family Polymorphism 590P Seminar February 16, 2005](https://reader036.vdocuments.mx/reader036/viewer/2022062423/56649ef25503460f94c04534/html5/thumbnails/26.jpg)
build() in gbeta
build: (# g:<@Graph; n:^g.Node; e:^g.Edge; b:@boolean enter (n[],e[],b) do n->e.n1[]->e.n2[]; (if (e->n.touches)=b then ‘OK’->putline if)#);g1:@Graph; g2:@OnOffGraph
(g2.Node, g1.Edge, false) -> build(#g::@g2#);
TYPE ERROR! (because g1 ≠ g2)
![Page 27: Family Polymorphism 590P Seminar February 16, 2005](https://reader036.vdocuments.mx/reader036/viewer/2022062423/56649ef25503460f94c04534/html5/thumbnails/27.jpg)
Family-polymorphic data structures
NodesAndEdges: (# g:< @Graph; nodes: @list(# element::g.Node #); edges: @list(# element::g.Edge #) #)
myGraph: @LabelledGraph;myNodesAndEdges: @NodesAndEdges(#g::@myGraph#)