/*

classes are functions:

	typeof Rectangle
		'function'

//----------------------------------------------------------
Javascript is a bit inconsistant when it comes to classes.

	We can get the superclass like this:
		Object.getPrototypeOf(Rectangle) === Shape

	The superclass of Shape is "Object"

	But the root class (Object) behaves differently
	We might expect this:

		Object.getPrototypeOf(Shape) === Object
		//but this is false

		//These are both true:
		Object.getPrototypeOf(Shape) === Object.__proto__
		Object.getPrototypeOf(Shape) === Object.getPrototypeOf(Object)

	This seems to be how we determine we have the Object class

		Object.__proto__.__proto__.__proto__

	or
		aSuper = Object.getPrototypeOf(Shape)
		aSuper.__proto__.__proto__
		//null

//----------------------------------------------------------

*/
class Shape {
	helloFromShape() { return "I am a shape"; }
}

class Rectangle extends Shape {
	holaFromRec() { return "I am a rectangle"; }
	toString() { return "Me Rectangle"; }
}

class CrazyRectangle extends Rectangle {
	holaFromRec() { return "I am a crazy rectangle"; }
	toString() { return "Me CrazyRectangle"; }
}

class AbstractInterfaceZz {
	constructor(anObject) {
		this.object = anObject;
	}
	o() { return this.object; }
}

class ObjectInterfaceZz extends AbstractInterfaceZz {
	getClass() {
		return this.o().constructor;
	}
	getClassName() {
		return this.getClass().name;
	}
	getSuperclass() {
		return Object.getPrototypeOf(this.getClass());
	}
	getProto() {
		return Object.getPrototypeOf(this.o());
	}
	getInstanceMethods() {
		return Object.getOwnPropertyNames(this.getProto());
	}
}

class ClassInterfaceZz extends AbstractInterfaceZz {
	getSuperclass() {
		return Object.getPrototypeOf(this.o());
	}
	getSuperclassName() {
		let sc = this.getSuperclass();
		let nm = sc.name;
		if (!nm && sc.__proto__.__proto__ == null)
			return 'Object';
		return nm;
	}
	isRootChild() {
		//e.g. is our superclass 'Object'
		//seems we need to be a bit kludy here
		let aSuper = this.getSuperclass();
		return aSuper.__proto__.__proto__ == null;
	}
}

//----------------------------------------------------------------

Object.prototype.zzo = function() {
	return new ObjectInterfaceZz(this.valueOf());
}

Object.prototype.zzc = function() {
	return new ClassInterfaceZz(this.valueOf());
}


//----------------------------------------------------------------

var rec;
let prn = console.log;

rec = new Rectangle();
prn("rec class: " + rec.zzo().getClassName());
prn("rec superclass: " + rec.zzo().getSuperclass().name);
prn(`rec methods: [${rec.zzo().getInstanceMethods()}]`);

prn("rec superclass of superclass (grandparent class): " + rec.zzo().getSuperclass().zzc().getSuperclassName());

let crazy = new CrazyRectangle();
prn("crazy superclass of superclass (grandparent class): " + crazy.zzo().getSuperclass().zzc().getSuperclassName());

let recSuper = rec.zzo().getSuperclass();
prn(`${recSuper.name} is root child: ${recSuper.zzc().isRootChild()}`);
prn(`${Rectangle.name} is root child: ${Rectangle.zzc().isRootChild()}`);
prn(`${AbstractInterfaceZz.name} is root child: ${AbstractInterfaceZz.zzc().isRootChild()}`);
prn(`${ClassInterfaceZz.name} is root child: ${ClassInterfaceZz.zzc().isRootChild()}`);


Navigation