Before I go on:
This is an absolutely abstracted question. Don't ask what are you trying to do.
Here's the thing:
Look at this two pieces of code in two different syntax. (syntaxes?)
I use the second one almost exclusively, and comes with the 2nd one an ability that's not possible in the other one.
I don't know about OO in Java/C#.
I want to know where Java/C# stand, on this ability.
My question is about that ability, and:
If that ability is possible in C#/Java? (I know that it's not possible in the first syntax)
Is it totally flawed in terms of OO principles in C#/Java? (cuz I tought maybe there's a reason it's not possible in the first syntax)
Is it an unwanted thing?
While I'm not sure about the terminology, this ability that I'm talking about is returing the super.
the first syntax: (which is es6 stuff)
var log = console.log;
class Gender {
constructor(type) {
this.gender = type;
}
sayGender() {
log(this.gender);
return this;
}
}
class Person extends Gender {
constructor(gender, name, age) {
super(gender);
this.name = name;
this.age = age;
}
sayName() {
log(this.name);
return this;
}
sayAge() {
log(this.age);
return this;
}
saySomething() {
// only limited access to super methods.
// access limited to calling super methods/getters/setters and not public properties.
// (also not possible to return them since they're just imaginary refrences and not values)
// this === invoked instance
// super === reference to implicit derived instance (not returnable since not value)
// no access to super/base instance (instance of Person)
log("you can't break the chain here, even if u wanted to");
return this;
}
class Employee extends Person {
constructor(gender, name, age, jobTitle) {
super(gender, name, age);
this.jobTitle = jobTitle;
}
sayJob() {
log(this.jobTitle);
return this;
}
}
here's the second syntax
var log = console.log;
function newGender(type) {
let inst = {};
inst.gender = type;
inst.sayGender = function () {
log(gender); // or this.gender if u want (but context-less calls will no longer be available)
return this;
};
return inst;
}
function newPerson(gender, name, age) {
let _super_ = newGender(gender);
let inst = Object.create( _super_ );
let privateVariable;
function privateFunction() {} // not possible with the other syntax
inst.name = name;
inst.age = age;
inst.sayName = function () {
log(name);
return this;
};
inst.sayAge = function () {
log(age);
return this;
};
inst.saySomething = function () {
// full access to super/base, derived, and invoked instances. (even returning them since they're values now).
// differentiation between super/base, derived, and invoked instances in the context of current class.
// _super_ === base instance
// inst === derived instance
// this === invoked instance
log("you can break the chain here if u want");
return inst;
};
return inst;
}
function newEmployee(gender, name, age, jobTitle) {
let _super_ = newPerson(gender, name, age);
let inst = Object.create( _super_ );
inst.jobTitle = jobTitle;
inst.sayJob = function () {
log(jobTitle);
return this;
};
return inst;
}
Diffs:
method chaining:
var t = new Employee("male", "mohammad", 28, "web developer")
t.sayGender() // "male"
.sayName() // "mohammad"
.sayAge() // 28
.saySomething() // "you can't break the chain here, even if u wanted to"
.sayJob() // "web developer"
var t = newEmployee("male", "mohammad", 28, "web developer")
t.sayGender() // "male"
.sayName() // "mohammad"
.sayAge() // 28
.saySomething() // "you can break the chain here if u want"
// I can't chain after this point since I returned the super and sayJob() is not defined on it.
.sayJob() // "web developer"
context-less calls:
var t = new Employee("male", "mohammad", 28, "web developer")
var sayJob = t.sayJob;
sayJob() // TypeError: Cannot read property 'jobTitle' of undefined
var t = newEmployee("male", "mohammad", 28, "web developer")
var sayJob = t.sayJob;
sayJob() // web developer
Edit:
The question is not about Java or C# or JavaScript.
When you call the constructor of a derived class in JavaScript (with new
)
there is an implicit super instance available for your derived instance (since all derived class constructors must contain a super() call). But you can only use methods (and getters/setters) of this implicit instance and not properties.
So inside the sayName()
method of the Person
class I can say super.someMethod()
or super["name of a setter"] = "a value";
or super["name of a getter"]; // and u can read it
So I have access to the super instance but my access is limited.
Hence why you can't return it, yes I know super
is not a value =)))).
Now imagine you get full access to the instance that super
points to. right?
What I mean by full access is imagine you get that instance right there as a value, So now you can return it or whatever.
What I'm asking you is If you're a Java/C# developer and you work with hierarchical inheritance a lot and have experience in doing so, tomorrow I will show up at where you work, or email you or something and I will tell you that I have a big news for you:
from this day forward there's gonna be two changes in Java/C# lang:
1 super
now points to the base class instance.
2 super
is now a value, is an actual instance in the context of your derived class, and you can do whatever you want with it. YOU CAN EVEN RETURN IT IN A METHOD!!!
What do you say? what are your thoughts?
(one scenario would be that now a method can return the super instance, and if somebody is chaining some methods from outside and calls this method the next instance that will be returned will not have the derived instance methods anymore)
Final Edit: The way I would write this question after the discussions in comments (though I'm not sure if this way is better or not since it's longer):
In JavaScript a class, behaves as follow: (and when I say a class I mean the fake classical inheritance that we pretend it to be with the underlaying prototypal system)
It must have a constructor which is called when you instantiate it with a new
kewrod (var t = new Person()
) and you get an instance (or object) of that class.
So when you're defining your class eg:
class Person() { // from this curly
} // to this curly
You can reference that instance that will get created if someone calls new
.
Not a complicated thing so far. Let's keep going.
So a class can be derived from another class. and this thing adds to the complexity. why? well let's see:
Now we must go through the behaviour of a derived class.
A derived class shares the same behaviours with a base class except a few:
A derived class has a constructor and inside those curlies you would reference the instance (that will get created after the call to new
), and all of that, just like a base class.
But a derived class has some behaviours which it doesn't share with the base class. so let's go through them, here's a derived class definiteion:
class Employee extends Person {
constructor() {
super()
}
}
A derived class while has a constructor just like a base class, it also has an aditional rule that is: its constructor must contain a super()
call, what that does is it's going to call the base class constructor. So now inside the curlies of a derived class in adition to the this
keyword (which was the to be created instance) we also have a super
keyword.
What the super
keyword allows you to do is to reference an object just like this
except that it's not the object that you would get if you would call new
no it's not that object, it's the object that you would get if you would instantiate the base class (new Person()
), but it differs from you instantiating that base class manually, how it differes? It differes because if you would've isntantiate that base class manually with a new
call you would've get all the public methods, properties, getter and setters of that class. but that's not extactly what's happening with the super
keyword.
So with the super
keyword although you are actually referencing that instance of the base class and there is an (implicit) instance of that base class avaiable for your derived instance (inside the curlies), you don't get to access the properties (even the public ones) of that instance you only get to use public methods. (while there's no public private in es6 js, but let's pretend it is. like typescript).
So now we see that inside the curlies of a devided class we have access to that instance, though limited to methods, but still access and important to remeber that the super
keyword is like an imaginary thing and is not a value.
So everything normal so far nothing special. Here's my dilemma:
Due to JavaScript internal system, I have an ability which gives me an option for when I'm constructing objects, let's see what that ability is and more importantly and finaly my question about that ability:
This ability that I keep mentioning is:
Remeber that I said: super
is just like an instance of a base class that you manually instantiated but with limitations? well now I can treat the super
as if it was really an instance of the base class that I manually instantiated. so now not only I get to access all of it's members (properties and methods) withouth the limitations of super
, but since it's a value now, I get to return it in a derived method as well, and cause a chain break (which I feel like it's sorta like a better not to have and not need etc etc deal).
The following are the two abilities that I can come up with so far:
#1 One aspect is when you chain methods, with the class syntax, I would always have one instance, one object. and after one step in a chain. I could access all methods of that instance, and the fact that some of those methods are owned and some of them are inherited wouldn't matter. but with the value kind super
I could put stop breaks in that chain. so what could be the use of it? Well I'm not sure, but what I can think of right now is maybe I could have a cue to differentiate between owned and inherited methods. so now If a method breaks the chain I know that that method is been inherited somewhere up the hiearchy.
#2 One other aspect is context-less calls, but let's ingore it as I'm not sure if there's such thing in Java/C#. (but shortly just to be clear: context-less call means you call the method without a context, or in another words, without providing which object should this
keyword points to).
These two abilities are the ones that stump me, as I don't know the reasoning in O-O the way I want to know (like the back of my hand), so while I like these abilities, I'm not sure where they would lead the system. and I don't know how to measure it or how to foresee the future of it, so I thought to ask for the opinion of a Java/C# programmer.
P.S. Both of the updated answers are accepted answers.