#!perl6 class Person { ... } class Thing { ... } class Container { ... } class Place { ... } class Nowhere { ... } class Entity { use JSON::Tiny; my %cache; has $.id is rw; method Str { self.id } method load(Entity: $id) { return Nowhere if $id eq 'nowhere'; return %cache{$id} if %cache{$id}:exists; my %hash = from-json slurp "$id.json"; my $class = %hash:delete; if (%hash:exists) { %hash = Entity.load(%hash); } %hash = $id; %cache{$id} = sub ($_) { return Person.new(|%hash) when 'Person'; return Place.new(|%hash) when 'Place'; return Container.new(|%hash) when 'Container'; return Thing.new(|%hash) when 'Thing'; }($class); warn "still here"; return %cache{$id}; } method json { my %hash; for self.^attributes -> $a { try { # Fails on undefined $.location, with # «Invocant requires an instance of type , but a type object was passed. # Did you forget a .new?» %hash{ $a.Str.substr(2) } = $a.get_value(self).Str } }; %hash = self.^name; return to-json %hash; } } class Place is Entity { has Entity $.location is rw where Place; } class Person is Entity { has Entity $.location is rw where Place = Nowhere; } class Container is Entity { has Entity $.location is rw where Place|Container = Nowhere; } class Thing is Entity { has Entity $.location is rw where Place|Container|Person = Nowhere; } class Nowhere is Place { submethod Str { "nowhere" } } #my $t = Thing.new; my $t = Entity.load("foo"); #$t.location = Place.new(id => "lhq"); say $t.perl; say $t.json; say $t.location.json;