Closed skatcat31 closed 5 years ago
In this example a Python(almost identical), Java, and C++ developer would easily be able to recognize that the ancestor variable is a static class variable(single instance of the variable, accessible by all instances) that can be modified by a single instance, and then fetched on any instance.
... What? The equivalent Java code:
class Person {
String ancestor = "monkey";
}
creates an instance variable, not a static variable. Try it.
To create a static variable in Java, you'd do
class Person {
static String ancestor = "monkey";
}
and in JS with this proposal you would do
class Person {
static ancestor = "monkey";
}
i.e., pretty much just like the Java version.
While you're right on Java, Java has a confusing way of defining classes anyways... Competing constructors that can be anywhere in a Class makes it a fun hunt and peck exercise. I'm not certain we'd want to adopt that version when we've already adopted the Python constructor version of keywords and assignment in constructor. I'll remove the list of langauge and make more about implimentation since while a similar concept, they all implement differently.
Python however has a direct collision: https://www.geeksforgeeks.org/g-fact-34-class-or-static-variables-in-python/
# Python program to show that the variables with a value
# assigned in class declaration, are class variables
# Class for Computer Science Student
class CSStudent:
stream = 'cse' # Class Variable
def __init__(self,name,roll):
self.name = name # Instance Variable
self.roll = roll # Instance Variable
# Objects of CSStudent class
a = CSStudent('Geek', 1)
b = CSStudent('Nerd', 2)
print(a.stream) # prints "cse"
print(b.stream) # prints "cse"
print(a.name) # prints "Geek"
print(b.name) # prints "Nerd"
print(a.roll) # prints "1"
print(b.roll) # prints "2"
# Class variables can be accessed using class
# name also
print(CSStudent.stream) # prints "cse"
They do however do not have predefined instance variables either. This is the closest to the ES6 class declaration. This also helps maintainability by keeping all member/instance variables in a single defined place.
C++ is a little bit more odd in it's decleration of Static Class Variables
:
http://www.learncpp.com/cpp-tutorial/811-static-member-variables/
class Something
{
public:
static int s_value;
};
int Something::s_value = 1;
int main()
{
Something first;
Something second;
first.s_value = 2;
std::cout << first.s_value << '\n';
std::cout << second.s_value << '\n';
return 0;
}
It sets them afterward, but still declares them in the class body.
In addition to Java, C++'s static
s are also pretty much like this proposal's:
class Something {
static int a; // static variable
int b; // instance variable
};
So are PHP's:
class Something {
public static $a = 1; // static variable
public $b = 2; // instance variable
}
So are Swift's:
class Something {
static var a = 1 // static variable
var b = 1 // instance variable
}
Python's class
is pretty unusual in a number of ways, this among them. But since we're following the precedent in most related languages which have classes, I'm not too worried.
I noted that this could probably be avoided by key wording statics as well. The problem is we aren't adhering to those classes in ES. We adhere to Python and other key worded constructor dynamic languages more so than the OOP version and it's what skyrocketed adoption of ES classes. So maybe this issue is moot more so and it should be clarified that it's conflicting with other similar language principles. Which is more likely the case. I'll update the title to match.
What languages other than python have that particular behavior for classes?
R, Ruby, Perl to name three common ones
Ruby, yes, although in my experience Ruby's behavior here tends to surprise people. In what sense do R and Perl share this behavior?
R has the same 'variables outside of constructor are static class variables' and Perl has the same sense of module scoped variables for static variables to the class(meaning outside of class constructor are static class variables
because of closures) however Perl's exact syntax means it kind of actually matches the IIFE pattern more precisely.
basically key worded constructors languages with closures consider variables outside the class to be static if in closure.
Sorry, to be precise, I meant that the things R and Perl call classes are not very syntactically similar to JavaScript's classes, so it's hard for me to see what you mean when you say that they have the same behavior as Python. The examples I gave are all very syntactically similar to JavaScript and have correspondingly similar semantics. Could you give an example of idiomatic R and/or Perl code which you think would lead programmers only familiar with those languages to be surprised by the proposed JavaScript behavior?
I also don't know what you mean by "key worded constructors languages". PHP and Swift both use keyword-like method names to declare class constructors (__construct
and init
respectively), for example - is that what you mean?
@bakkot key worded constructor languages are languages that only allow constructors and that the constructor is where you assign member variables to the instance. It means that in a class, constructors are uniquely referenced and has a specified purpose. Constructors will always be the method called when you use new Class()
if present.
As for R:
make.f <- function() { # class decleration
count <- 0 # static class variable
f <- function(x) {
count <<- count + 1
return( list(mean=mean(x), count=count) )
}
return( f )
}
As for Perl:
package Bar; # class(package) decleration. It's what gets imported
use strict;
use warnings;
sub new { bless {}, shift }; # constructor
my $foo = 123; # class variable with getter, setter possible
sub get_foo { $foo }
our $fubb = 456; # can be access on the class as Bar::fubb
Perl like I said is probably closer to the IIFE method of defining it, but outside of the constructor is where you are accessing it.
It means that in a class, constructors are uniquely referenced and has a specified purpose. Constructors will always be the method called when you use new Class() if present.
OK. That definition includes both PHP and Swift, both of which have closures (in some sense), and both of which behave like this proposal; I'm not sure this dichotomy is as strong as you are suggesting.
As for R: / As for Perl:
Thanks for these examples. Since these are very dissimilar from JavaScript's class syntax, I am not very worried about programmers coming from those languages being surprised by this particular piece of this proposal.
Then I need to clarify the definition. Rereading it I seem to have word garbled(as well as taken a hatchet to grammar)
Key worded constructor languages are languages that limit member variable assignment to the constructor methods.
As for R example translating it to JS:
class f{
count = 0
// class has no constructor because no instance variables
f (x) {
count += 1
return [mean(x), count]
}
}
As for Perl example translation to JS:
class Bar{
foo = 123
constructor(){...}
get foo() {
return foo
}
}
Bar.fubb = 456
My impression is that the Python semantics are unusual compared to other languages and a bug farm, rather than a good concept to be copied. For the other examples, JavaScript closures can provide the analogous behavior.
NOTE: I am not talking about
Static Variables
which are on instances of the class, but can never be changed. These by another name are calledgetters without setters
Classes were created as a way to make ES6 more approachable from users of other languages and to solve the problem of prototype pollution. It also lead to more maintainable code. That made it instantly recognizable to developers of any other language by design and drove adoption rates. Now this proposal seems to compete with a prior art from other key worded dynamic languages and threaten to pollute what should and should not belong in a constructor and give it a footprint that is confusing to any adopting developers from Python,or any other language that implements the
Static Class Variable
concept and key worded constructors. Why would we want to meld the Python constructor keyword and member variable declaration pattern with the Java/C++/PHP instance variable declaration pattern leading to multiple places to declare instance variables?In this example a Python(almost identical), Java, and C++ developer would easily be able to recognize that the ancestor variable is a
static class variable
(single instance of the variable, accessible by all instances) that can be modified by a single instance, and then fetched on any instance. We currently do this in ES6 with IIFE statements:This is also a concept used consistently in React/Redux environments to pass a single instance of the state around to the React Classes to be used and is still accessed in the constructor to be referenced by the member. The slight difference being that redux maps it to a props key instead of just adding it to decleration, but the single instance accessible to all inheriting children with a concurrent state is similar in concept, if not exact in execution.
While this could just fall under another keyword, it shows collision with widely adopted principles that are extremely similar and the prior art in JS and other similar languages that do impliment
static class variables
in this way(Python, R, Ruby, Perl).