While going through this link
How to Deep clone in javascript
I came across a generic clone method (In the accepted answer) . I tried it out running directly in javascript and it runs giving perfect outputs.
I put that code in the native tag and am trying to clone an object in GWT.
My class which am trying to clone is
private class Container
{
Integer i = 5;
}
and when I try to do that, its just returning me the same object. Could anyone please help?
Ask me anything if its not clear. Thanks a ton.
Jonathan is right: the way (and the only one in GWT) is to use https://code.google.com/p/google-web-toolkit/wiki/AutoBean
This may seam awkward but it works perfectly since many concepts are related to that (EntityProxy in RequestFactory relies also on that mechanism, and it's the future of GWT).
Deep json persistence also works with auto beans.
The only thing you have to do is to create an interface that describes your class (and implement it in your class):
public interface ContainerBean {
Integer getI();
void setI(Integer i);
}
Then create your factory interface
interface MyFactory extends AutoBeanFactory {
// Factory method for a simple AutoBean
AutoBean<ContainerBean> container();
// Factory method for a non-simple type or to wrap an existing instance
AutoBean<ContainerBean> container(ContainerBean toWrap);
}
Now you can wrap your object and clone it (through json since)
clone()
An AutoBean and the property values stored within it can be cloned.
The clone() method has a boolean parameter that will trigger a deep or
a shallow copy. Any tag values associated with the AutoBean will not
be cloned. AutoBeans that wrap a delegate object cannot be cloned.
https://code.google.com/p/google-web-toolkit/wiki/AutoBean#clone()
therefore use this method instead:
https://code.google.com/p/google-web-toolkit/wiki/AutoBean#AutoBeanCodex
One way you could possibly achieve this is with AutoBeans.
I think the only trick with this method is that you'll have to use an AutoBeanFactory to create all of your classes.
Then, you could encode your autobean into a Splittable, then use the result to decode into a new autobean instance.
Related
Have done quite a bit of research on this but my situation seems to be a tad more complex than other examples i've seen on stack. I hope my explanation is clear enough to follow!
The API response I am working with is structured as an array of Customers. Each Customer has methods of its own as well as multiple nested objects. For the purposes of this question I'll focus on the Addons nested object (so Customer.Addons). Addons has some methods as well as an array of objects (addons). Each array item is an Addon object. So...I need to cast each level as the prototype of the associated Class.
This seems to work fine for Customer:
Object.setPrototypeOf(customer, Customer.prototype)
I am stuck on Addons even though I am using the same approach:
Object.setPrototypeOf(customer.addOns, Addons.prototype)
And for the array of addons (type Addon) I am iterating through like so. THIS seems to be working fine as well:
_.each(customer.addOns, (addon: Addon) => {
Object.setPrototypeOf(addon, Addon.prototype)
})
When I console.log this stuff, I can see that the Customer object is getting recognized as Customer. I can see that array items are correctly getting recognized as type Addon, but the Addons object, that middle layer, seems to be a plain object.
This image captures what I mean. Parent object of type Customer, child named addons with an array of items all of type Addon:
Here is my Addons class. It extends a generic class whose sole job is to have an array with some basic CRUD methods. The getSubtotal method is just returning a hard coded number for now (for testing) but will ultimately iterate through the associated array in its super and add numbers.
export class Addons extends PluralOfType<Addon> {
constructor() {}
...
getSubTotal(): number {
// eventually will return _.reduce(super.arr, ...) etc
return 10
}
}
Here is a segment from the PluralOfType generic:
class PluralOfType<T> {
public arr: T[] = [];
getAll(): T[] { return this.arr };
...
}
In my other typescript files, if I do this:
console.log(customer.addOns)
I will get the array of addons, each of type Addon. If I do this:
console.log(customer.addOns.getSubtotal())
I will get 10, which is correct. If I do this, which is a method on addOns superclass:
console.log(customer.addOns.getAll())
I get undefined. Moreover, because arr is public in the superclass, unsure why I can't just call customer.addOns.arr.
Clearly I am missing something here. Hopefully it's a simple fix! Appreciate any help.
Given some class object, class A {m(){}}, setting the prototype of an object, say o, to A.prototype does not construct A and then merge the resulting value's members into o. It just changes o's prototype. In other words it sets up delegation of member lookup such that, if o does not have a requested member, say m, then A.prototype will be considered and A.prototype.m will be reolved.
So, for
class PluralOfType {
arr = [];
getAll() {return this.arr;}
}
and
class AddOns extends PluralOfType {
getSubTotal() {return 10;}
}
if we write
const o = {};
Object.setPrototypeOf(o, AddOns.prototype);
console.log(o.getAll());
will print undefined because this is o in the expression this.arr.
We would then likely be tempted to write
const addOnsArray = customer.addOns.slice();
Object.setPrototypeOf(customer.addOns, AddOns.prototype);
Object.assign(customer.addOns, new AddOns());
But that will make arr an empty array which isn't what we actually want.
An unsound and dirty fix for the specific problem is to write
const addOnsArray = customer.addOns.slice();
Object.setPrototypeOf(customer.addOns, AddOns.prototype);
customer.addOns.arr = addOnsArray;
This in not general enough to be useful.
The entire approach dramatically increases the odds of introducing very serious and difficult to find bugs. It makes the system confusing.
I'm not just talking about arrays, I mean all of it.
You should scrap your entire approach. Don't change the prototypes of any values returned by JSON.parse at all.
You probably do not realize how hard you are making your task nor how much the people who inherit your project will hate you.
My recommendation is that you not use classes to define the functionality. If you really want to have methods in your objects add them to the objects directly. However, it would be simpler to keep the functionality outside the objects either as free standing functions or as methods in services. These would receive the object as an argument. Sometimes it does make sense to have functions and data together but this does not work well with serialization.
I'm trying to get a better understanding of object oriented patterns in JavaScript. I particulary like the way EmberJS implements their classes with .extend and .create from Parent class Objects.
I've tried to implement a basic version of this on my own, but to no success, my newly instantiated Objects reference the same Object. I.e If I increment a private counter var in instance a via a public method, then separately do the same to instance b, b will reflect both increments.
I was able to achieve a de-referenced object via Object.create(myClass), however this is undesirable as I'd like to achieve this internally and also not rely on client support for that native method.
Here's a jsbin of what I've got: http://jsbin.com/zepaju/6/edit?js,console
Thanks for any help!
This is a pretty big subject, because there isn't a perfect way to make JavaScript work like Java-- you'll always have to invent some new coding idiom, and different people have different preferences.
Looking at your linked code, it's hard to be sure what you're gunning for but it looks like the problem is that you're thinking of an object's prototype as a "class", which is copied into each "instance" (like in Java)-- this isn't the case.
Your create() function is creating each "instance" by doing Object.create(Poll), which makes a new object with the Poll object as its prototype. When you refer to properties of the resulting objects, and those properties are not directly defined on the object, what you get is a reference to a property of the single Poll object.
The fact that you've sealed the Poll object's internal variables within a closure doesn't make any difference to this; the closure variables are hidden from the outside world, but they are accessible to the methods of the Poll object, and those methods are shared between all "instances".
If you want a function that spits out objects with a particular set of methods, and which hide their internal data in a closure, that might look like:
function Poll(challenger,incumbent) {
var challengerVotes=0;
var incumbentVotes=0;
return {
voteForChallenger: function() {challengerVotes++},
voteForIncumbent: function() {incumbentVotes++},
winner: function() {return challengerVotes>incumbentVotes ? challenger : incumbent}
}
}
var poll1 = Poll("Edward","Jacob");
var poll2 = Poll("Vanilla","Stilton");
poll1 and poll2 would not affect one another, and there would be no way to access the vote counts of either except through the supplied methods. I appreciate you're looking for a more generic approach but this is an example of how you might start.
I'm coming from C/C++ syntax family so some things here aren't familiar to me.
constructor: function(manufacturer, model, topSpeed, maxAltitude){
// initialise our config object
this.initConfig();
if(maxAltitude){
this.setMaxAltitude(maxAltitude);
}
// call the parent class' constructor
this.callParent([manufacturer, model, topSpeed]);
}
So, now when I'm calling a parent's constructor, why am I including data in []? When I did something similar in C#, I just send data like in any normal function.
Couldn't this just be:
this.callParent(manufacturer, model, topSpeed);
This example is from
Ext-JS 4 Web Application Development Cookbook
but I think it's a JavaScript problem.
Thank you.
Well .callParent() is a class system utility provided by ExtJS. It needs the arguments as an array because it's going to use .apply() to call another function.
They could have written it to build its own array if they'd wanted to. It's arguably more useful in the current form because it gives you more flexibility, and it's not like making an array is hard in JavaScript.
(I don't know exactly what it does because I don't use ExtJS.)
Is it possible to create an object container where changes can be tracked
Said object is a complex nested object of data. (compliant with JSON).
The wrapper allows you to get the object, and save changes, without specifically stating what the changes are
Does there exist a design pattern for this kind of encapsulation
Deep cloning is not an option since I'm trying to write a wrapper like this to avoid doing just that.
The solution of serialization should only be considered if there are no other solutions.
An example of use would be
var foo = state.get();
// change state
state.update(); // or state.save();
client.tell(state.recentChange());
A jsfiddle snippet might help : http://jsfiddle.net/Raynos/kzKEp/
It seems like implementing an internal hash to keep track of changes is the best option.
[Edit]
To clarify this is actaully done on node.js on the server. The only thing that changes is that the solution can be specific to the V8 implementation.
Stripping away the javascript aspect of this problem, there are only three ways to know if something has changed:
Keep a copy or representation to compare with.
Observe the change itself happening in-transit.
Be notified of the change.
Now take these concepts back to javascript, and you have the following patterns:
Copy: either a deep clone, full serialization, or a hash.
Observe: force the use of a setter, or tap into the javascript engine (not very applicable)
Notify: modifying the code that makes the changes to publish events (again, not very applicable).
Seeing as you've ruled out a deep clone and the use of setters, I think your only option is some form of serialisation... see a hash implementation here.
You'll have to wrap all your nested objects with a class that reports you when something changes. The thing is, if you put an observer only in the first level object, you'll only receive notifications for the properties contained in this object.
For example, imagine you have this object:
var obj = new WrappedObject({
property1: {
property1a: "foo",
property1b: 20,
}
})
If you don't wrap the object contained in porperty1, you'll only receive a "get" event for property1, and just that, because when someone runs obj.property1.property1a = "bar" the only interaction that you'll have with obj, will be when it asks for the reference of the object contained in property1, and the modification will happen in an unobserved object.
The best approach I can imagine, is iterating over all the properties when you wrap the first object, and constructing recursively a wrapper object for every typeOf(property) == "Object".
I hope my understanding of your question was right. Sorry if not! It's my first answer here :$.
There's something called reactive programming that kind of resembles what you ask about, but its more involved and would probably be overkill.
It seems like you would like to keep a history of values, correct? This shouldn't be too hard as long as you restrit changes to a setter function. Of course, this is more difficult in javascript than it is in some other languages. Real private fields demand some clever use of closures.
Assuming you can do all of that, just write something like this into the setter.
function setVal(x)
{
history.push(value);
value = x;
}
You can use the solution that processing.js uses.
Write the script that accesses the wrapped object normally...
var foo = state.get();
foo.bar = "baz";
state.update();
client.tell(state.recentChange());
...but in the browser (or on the server if loading speed is important) before it runs, parse the code and convert it to this,
var foo = state.get();
state.set(foo, "bar", "baz");
state.update();
client.tell(state.recentChange());
This could also be used to do other useful things, like operator overloading:
// Before conversion
var a=new Vector(), b=new Vector();
return a + b * 3;
// After conversion
var a=new Vector(), b=new Vector();
return Vector.add(a,Vector.multiply(b,3));
It would appear that node-proxy implements a way of doing this by wrapping a proxy around the entire object. I'll look into more detail as to how it works.
https://github.com/samshull/node-proxy
Is there a way to access the super object when extending objects using $.extend?
I would like to extend an object, override a method, but call the overridden superclass method in the subclass method.
No, because there is no superclass. According to the docs for jQuery.extend:
Description: Merge the contents of two or more objects together into the first object.
In order to call a "superclass" method, you would have to keep a copy of the "superclass" around somewhere (perhaps as a parameter in the "descendant" object), and call the method directly on the "superclass".
If you are looking for javascript inheritance, you may be interested in this post from John Resig.
Not directly -- the old method is not longer around (except in the original object).
I've done two things: The first is to make a copy of the old method with a new name in the subclass:
var Super = {
a: function() {...}
};
var _SubFuncs: {
_superA: Super.a
a: function() {... this._superA(...) ... }
};
var Sub = $.extend(false, Super, _SubFuncs);
The other thing I've done when appropriate is to use the template pattern and have the super class call a method that for it has no behavior. The subclass then add behavior to the empty method. This only works if your call structure is such that "holes" can be added appropriately.
Edit: In my case, I was really trying to stick with prototypal objects so I was avoiding a general solution that makes my objects more class-like.
If you want to use the class inheritance and call the super class methods, then this blog from John Resig explains it all http://ejohn.org/blog/simple-javascript-inheritance/