Javascript - creating method - object

I am very new to javascript. I find some sample code for creating a object method.
<script>
function person(firstname,lastname,age,eyecolor){
this.firstname = firstname;
this.lastname = lastname;
this.age = age;
this.eyecolor = eyecolor;
this.changeName = changeName; //Why do I need this? What's it for?
function changeName(name){
this.lastname = name;
}
}
....
</script>
My question is: Why do I need to write this.changeName = changeName (also comment above). What's it for?
Thanks!

I think the key point is that javascript stores functions in variables. So
function changeName(name){
this.lastname = name;
}
is equivalent to
changeName = function () {
this.lastname = name;
}
Hence just writing function changeName(..)... in the constructor will create a function which is stored in a local variable not a class member variable. To turn it into a class member you need to do this.changeName = changeName (notice that this is exactly the same as for other variables).
Typically people add class functions like this:
function person(firstname,lastname,age,eyecolor){
this.firstname = firstname;
this.lastname = lastname;
this.age = age;
this.eyecolor = eyecolor;
}
person.changeName = function(name) {
this.lastname = name;
}

Because in your class you have a property called changeName and you are passing in a parameter called changeName, by using "this" it will be referenced to the class property and not the parameter that you have passed in.
You don't have to use this, you can do something like:
function person(_firstname, _lastname, _age, _eyecolor){
firstname = _firstname;
lastname = _lastname;
age = _age;
eyecolor = _eyecolor;
changeName = _changeName; //Why do I need this? What's it for?
function changeName(name){
this.lastname = name;
}
}
So basically by using this, it will just be able to tell apart from the local scope and class scope variables.

Related

Apache Calcite - ReflectiveSchema StackoverflowError

I'm trying to create a simple schema using ReflectiveSchema and then trying to project an Employee "table" using Groovy as my programming language. Code below.
class CalciteDemo {
String doDemo() {
RelNode node = new CalciteAlgebraBuilder().build()
return RelOptUtil.toString(node)
}
class DummySchema {
public final Employee[] emp = [new Employee(1, "Ting"), new Employee(2, "Tong")]
#Override
String toString() {
return "DummySchema"
}
class Employee {
Employee(int id, String name) {
this.id = id
this.name = name
}
public final int id
public final String name
}
}
class CalciteAlgebraBuilder {
FrameworkConfig config
CalciteAlgebraBuilder() {
SchemaPlus rootSchema = Frameworks.createRootSchema(true)
Schema schema = new ReflectiveSchema(new DummySchema())
SchemaPlus rootPlusDummy = rootSchema.add("dummySchema", schema)
this.config = Frameworks.newConfigBuilder().parserConfig(SqlParser.Config.DEFAULT).defaultSchema(rootPlusDummy).traitDefs((List<RelTraitDef>)null).build()
}
RelNode build() {
RelBuilder.create(config).scan("emp").build()
}
}
}
I seem to be correctly passing in the "schema" object to the constructor of the ReflectiveSchema class, but I think its failing while trying to get the fields of the Employee class.
Here's the error
java.lang.StackOverflowError
at java.lang.Class.copyFields(Class.java:3115)
at java.lang.Class.getFields(Class.java:1557)
at org.apache.calcite.jdbc.JavaTypeFactoryImpl.createStructType(JavaTypeFactoryImpl.java:76)
at org.apache.calcite.jdbc.JavaTypeFactoryImpl.createType(JavaTypeFactoryImpl.java:160)
at org.apache.calcite.jdbc.JavaTypeFactoryImpl.createType(JavaTypeFactoryImpl.java:151)
at org.apache.calcite.jdbc.JavaTypeFactoryImpl.createStructType(JavaTypeFactoryImpl.java:84)
at org.apache.calcite.jdbc.JavaTypeFactoryImpl.createType(JavaTypeFactoryImpl.java:160)
at org.apache.calcite.jdbc.JavaTypeFactoryImpl.createStructType(JavaTypeFactoryImpl.java:84)
What is wrong with this example?
Seems that by just moving the Employee class a level above, ie. making it a sibling of the DummySchema class, makes the problem go away.
I think the way the org.apache.calcite.jdbc.JavaTypeFactoryImpl of Calcite is written doesn't handle Groovy's internal fields well.

How can I set global field in method

I have some problem, so I have a few global fields in class, for each I want to do the same code but I don't want to repeat code - just use one method for that. And there I want to send these global fields in argument of this method and as second argument I want to send value for this field.
I tried with object, generic type but I don't know how to do that. Here is example:
private void setName(String _name) {
if(isNull(_name)) {
this.name = "";
} else {
this.name = _name.toString();
}
}
And a few other methods use the same code but with other fields and argument and I want to do something like that:
private void setField(some_field, _value) {
if(isNull(_value)) {
this.some_field = "";
} else {
this.some_field = _value;
}
}
Could someone help?
For example I have 2 global fields:
String name, int age.
For them I need to use the same code (if) and I want do it in one method. In this case I have to use global field as argument and as second argument use correct value for this field so instead:
this.name = argument;
this.age=argument;
use: globa_field_argument = argument;
Example:
setField( this.name, "Test" );
setField( this.age, 5 );
First off I would probably declare your global fields as 'public static'.
for example:
public static int myNumber = 10;
public static String myString = "foo";
Secondly you should have to pass your fields as an argument since you can access them inside the method itself.
When you redefine the fields anywhere in your code you will do this:
this.myNumber = newNumber;
this.myString = newString;

How to override "="

I was looking into Haxe abstracts and was very interested in building an abstract that would wrap a class and unify it to, in my case, an Int.
#:forward()
abstract Abs(Op)
{
public inline function new(value:Int = 0, name:String = "unnamed" )
{
this = new Op();
this.value = value;
this.name = name;
}
#:to
private inline function toInt():Int
{
return this.value;
}
}
class Op
{
public var value:Int = 0;
public var name:String = "no name";
public function new()
{
}
}
The problem I ran in to is when defining a #:from method - it has to be static and can take only one parameter - a new value. So whenever I set the abstract's instance value from the #:from method I will have to create a new instance of the abstract, thus resetting all the variables.
Basically what I'm talking about is this:
var a = new Abs(5, "my abs"); // value is 5; name is "my abs"
a = 100; // value is 100; name is reset to "unnamed" but I want it to be preserved
As much as I could find out we cannot overload the = operator in abstracts other than through implicit casting with a #:from method and I haven't found a way to really achieve this with macros.
If you have any ideas on how this can be done, please provide a minimalist example.
It depends what you want to do, but if you use this:
var a = new Abs(5, "my abs");
var myInt:Int = a;
It will use the abstract Abs.toInt function.
#:to
private inline function toInt():Int
{
return this.value;
}
The other way around also works:
var million = 1000000;
var myAbs:Abs = million;
It will use the static Abs.fromInt function.
#:from
static inline function fromInt(value:Int)
{
return new Abs(value, "what");
}
This is because it uses the implicit cast. http://haxe.org/manual/types-abstract-implicit-casts.html
Try it yourself: http://try.haxe.org/#Ae1a8
Is that what you are looking for?

Name generator using Generics

I am trying to generate a Name based on type of an object. In my system, I have,
class Employee {}
Class ContractEmp:Employee{}
class Manager:Employee{}
I am trying to generate name which looks like ContractEmp1 Where 1 will come from incrementer. I am trying to use Generics.
Any Help
Thank you,
With an extension method you could do something like this:
public static class NameExtension
{
private static Dictionary<string, int> counters = new Dictionary<string, int>();
public static string MakeUpName<T>(this T #object)
{
var t = typeof(T);
if ( ! counters.ContainsKey(t.FullName))
counters[t.FullName] = 0;
return t.Name + counters[t.FullName]++;
}
}
Test:
[TestFixture]
class NameTest
{
[Test]
public void test()
{
Console.WriteLine(new NameTest().MakeUpName());
Console.WriteLine(new NameTest().MakeUpName());
Console.WriteLine(new NameTest().MakeUpName());
Console.WriteLine(new NameTest().MakeUpName());
}
}
Output:
NameTest0
NameTest1
NameTest2
NameTest3
You can use a private static int in the Employee class which gets incremented on each constructor call. Combining this number with the typeof(this).Name value you can generate the names as described. Do note that the counter will count for all Employee extending classes so if you want an consecutive list of numbers for each Employee extending class, a specific counter should be implemented for every extending class. Also, the counters will be set to zero each time the application restarts.
public Class ContractEmp:Employee{
private static int counter = 1;
private String name = "";
public ContractEmp() {
name = typeof(this).Name + counter++;
}
}
Something like this should work!

C#: is it possible to create an object that has a value of its "default property" when referenced?

Is it possible to create an object with a constructor parameter which returns a property value when referenced, without using dot notation? Here's a few examples:
public class myObject
{
public string myObject {get; private set;}
public myObject( string tempstring)
{
this.myObject = tempstring.ToUpper();
}
}
var a = new myObject("somevalue");
Console.WriteLine( myObject ); // outputs the string "SOMEVALUE"
Here's another attempt:
public class myInt
{
public int myInt {get; private set;}
public myInt(string tempInt)
{ this.myInt = Convert.ToInt32(tempInt);
}
}
var a = new myInt("3");
var b = a + a; // ends up being an int datatype value of 6
I know I could always do var b = a.myInt + a.myInt. I guess I could create a static class with a static function that converts a parameter each time to a result, but it wouldn't maintain state.
Just curious. It would make what I am actually trying to do much less difficult.
In the first case, yes. Override the ToString method.
public class myObject
{
public string myValue {get; private set;}
public myObject( string tempstring)
{
this.myValue = tempstring.ToUpper();
}
public override string ToString()
{
return myValue;
}
}
In the second case, sort of. You shouldn't try to overload operators to offer unexpected behavior. Create a method to perform behavior that wouldn't make sense when reading the code. What you are suggesting (returning an int) would definitely not be expected by me to return an int (mostly because of the var rather than a strictly defined type). Using the + operator to return a new myInt object would make sense. Using the + operator return an int would not.
You could overload the + operator to return a new myInt object, and then also add an implicit cast to int. Just make sure it makes sense, and that it is readable.
Within the class, you could use:
public static implicit operator int(myInt m)
{
return myValue;
}
public static myInt operator +(myInt left, myInt right)
{
// requires constructor that takes int
return new myInt(left.myValue + right.myValue);
}
Of course, you could go the direct route, but again only use it when it makes it more readable and not less (note, just like methods operators cannot be overloaded simply by return type, so you'd have to pick between the two).
public static int operator +(myInt left, myInt right)
{
return left.myValue + right.myValue;
}
How about implicit conversions. See http://msdn.microsoft.com/en-us/library/z5z9kes2(VS.71).aspx

Resources