Object Encapsulation CSC 422 Dr. Spiegel
Outline Object Encapsulation Ownership Types
Encapsulation Level O raw lines of code Level 1 the procedural module class/object structure
Higher Levels of Encapsulation Packages and components (groupings of classes with only some of their interfaces visible externally Level -4 Compositions Design trade offs become more complex as encapsulation becomes more complex
~ ~ Object Encapsulation Consider a Set object s implemented using a Vector object v s o ~ ~ v Local reasoning about s is possible: If objects outside s do not access v v is encapsulated within s
Encapsulation In general, all objects that s depends on must be encapsulated within s s depends on x if mutations of x affect behavior of s
Iterators and Encapsulation Iterators require access to representation i s v Okay if violations of encapsulation limited to the same module
Ownership Types Goal is to enforce encapsulation statically v Programmer can declare s owns v System ensures v is encapsulated in s
Ownership Types Every object has an owner world Every object has an owner Owner can be another object or world Who owns main? Ownership relation forms a tree Owner of an object cannot change
Ownership Types for Encapsulation If an object owns objects it depends on the type system enforces encapsulation If v is inside s and o is outside, o cannot access v s o ~ ~ v
Ownership Types world
TStack Example (No Owners) class TStack { TNode head; void push(T value) {…} T pop() {…} } class TNode { TNode next; T value; … class T {…} TStack head value next value next value next TNode T … … … Can Tstack access Tnodes? Can a Tnode access T’s data?
TStack Example (With Owners) class TStackstackOwner, TOwner { TNodethis, TOwner head; } class TNodenodeOwner, TOwner { TNodenodeOwner, TOwner next; TTOwner value; class T TOwner {…} TStack TNode T Who owns the nodes? Classes are parameterized with owners
TStack Example class TStackstackOwner, TOwner { TNodethis, TOwner head; } class TNodenodeOwner, TOwner { TNodenodeOwner, TOwner next; TTOwner value; class T TOwner {…} TStack TNode T First owner owns the “this” object
TStack Example class TStackstackOwner, TOwner { TNodethis, TOwner head; } class TNodenodeOwner, TOwner { TNodenodeOwner, TOwner next; TTOwner value; class T TOwner {…} TStack TNode T TStack owns the “head” TNode
TStack Example class TStackstackOwner, TOwner { TNodethis, TOwner head; } class TNodenodeOwner, TOwner { TNodenodeOwner, TOwner next; TTOwner value; class T TOwner {…} TStack TNode T The “next” TNode has the same owner as the “this” TNode All TNodes have the same owner
TStack Example class TStackstackOwner, TOwner { TNodethis, TOwner head; } class TNodenodeOwner, TOwner { TNodenodeOwner, TOwner next; TTOwner value; class ClientclientOwner { TStackthis, this s1; TStackthis, world s2; TStackworld, world s3; Client TStack TNode T s1 is an encapsulated stack with encapsulated elements
TStack Example class TStackstackOwner, TOwner { world TNodethis, TOwner head; } class TNodenodeOwner, TOwner { TNodenodeOwner, TOwner next; TTOwner value; class ClientclientOwner { TStackthis, this s1; TStackthis, world s2; TStackworld, world s3; world Client TStack TNode T s2 is an encapsulated stack with public elements
TStack Example class TStackstackOwner, TOwner { world TNodethis, TOwner head; } class TNodenodeOwner, TOwner { TNodenodeOwner, TOwner next; TTOwner value; class ClientclientOwner { TStackthis, this s1; TStackthis, world s2; TStackworld, world s3; world TStack TNode T s3 is a public stack with public elements
TStack Example class TStackstackOwner, TOwner { TNodethis, TOwner head; } class TNodenodeOwner, TOwner { TNodenodeOwner, TOwner next; TTOwner value; class ClientclientOwner { TStackthis, this s1; TStackthis, world s2; TStackworld, world s3; TStackworld, this s4; // illegal TStack TNode T Other owners must be same as or more public than first owner This constraint is necessary to enforce encapsulation with subtyping
Constraints on Owners class ClientcOwner, sOwner, tOwner where (sOwner <= tOwner) { … TStacksOwner, tOwner head; } This is legal only if tOwner is same as or more public than sOwner
Iterators Consider an Iterator i over Stack s If i is encapsulated within s Then i cannot be used outside s If i is not encapsulated within s Then i cannot access representation of s TStack TStackEnum
Solution Use inner classes Gives desired access to representation Also satisfies modularity goal
Iterators TStack TStackEnum class TStackstackOwner, TOwner { TNodethis, TOwner head; …. class TStackEnumenumOwner, TOwner implements TEnumenumOwner, TOwner { TNodeTStack.this, TOwner current = TStack.this.head; } Inner class objects can access rep of outer class objects TStack TStackEnum
Ownership Types for Encapsulation If an object owns objects it depends on, then the type system enforces encapsulation If v is inside s and o is outside o cannot access v, unless o is an inner class object of s s o ~ ~ What must be true of o so we can declare an instance of o? v