Consider the instances of a Wrapper class. The Wrapper class has the ListProperty of ClassA instances and the ListProperty of ClassB instancies.
public class Wrapper {
private ListProperty<ClassA> aClasses;
private ListProperty<ClassB> bClasses;
public ListProperty<ClassA> aClassesProperty() { return aClasses; }
public ListProperty<ClassB> bClassesProperty() { return bClasses; }
// Methods…
}
The instances of ClassA and ClassB need to know if they are included in some Wrapper. They may be included only in one Wrapper or not be included at all.
public class ClassA { // Similarly ClassB
private Wrapper owner;
}
Some method of the Wrapper may remove member from one of ListProperties. I wonder if JavaFX has an automatic mechanism to notify a removed member of a ListProperty? Some binding mechanism between ListProperty of Wrapper and owner of ClassA/ClassB?
You can go by this way if you are in Wrapper class:
aClasses.getValue().addListener(
(ListChangeListener<ClassA>)event-> {
if (event.next()) {
if (event.wasAdded()) {
} else if (event.wasRemoved()) {
}
}
}
);
Or change to : owner.aClassesProperty().getValue().addListener( if you are in ClassA/B
But for JavaFX there is : FXCollections.observableList() dedicated to Listeners on List, learn more https://docs.oracle.com/javafx/2/collections/jfxpub-collections.htm at half-page and here https://docs.oracle.com/javase/8/javafx/api/javafx/collections/ObservableList.html
Related
So I have two sub classes that extend different base classes in Flex how can I combine these so that I am not repeating myself.
Basically I have something like
public class A extends B {
// methods
}
public class C extends D {
// same methods as class A
}
any way to combine this so that I am not repeating the same code twice.
Favor composition over inheritance
So, the question is, how should you compose the solution?
One possibility is to use Decorator pattern. This is essentially a wrapper around your existing Classes. To make this work, your Classes will probably need to implement an Interface that exposes whatever you'll need to do the job.
So something like:
public interface IFoo {
function get name():String;
function set name(value:String):void;
}
public class A extends B implements IFoo {
protected var _name:String;
public function get name():String {
return _name;
}
public function set name(value:String):void {
_name = value;
}
}
public class C extends D implements IFoo {
protected var _name:String;
public function get name():String {
return _name;
}
public function set name(value:String):void {
if (_value != _name) {
_name = value;
dispatchEvent(new Event('nameChanged'));
}
}
}
public class FooDecorator {
protected var _foo:IFoo;
public function FooDecorator(foo:IFoo) {
_foo = foo;
}
public function sayName():void {
trace('foo name is', _foo.name);
}
}
Another solution is to give both A and C member variables of a fifth type that encapsulate the behavior (like what Jeffry said, but I prefer to obey the law of Demeter where possible):
class NameSayer {
function sayName(name:String):void {
trace('foo name is', _foo.name);
}
}
then
public class A extends B {
public var name:String;
public var sayer:NameSayer;
//note that this method would be identical in both Classes
//but this is OK because the underlying logic is encapsulated
//and can be easily changed
public function sayName():void {
if (sayer) {
sayer.sayName();
}
}
}
I think many developers get too hung up on zealously following DRY and, as Jeffry says, this can cause other, worse, problems in your architecture. Which, if any, of these solutions is appropriate will depend on exactly what you're trying to accomplish.
You have two child classes (extending different parents) that implement the exact same methods.
public class B {}
public class D {}
public class A extends B {
// methods
m1();
m2();
...
}
public class C extends D {
// same methods as class A
m1();
m2();
...
}
Now lets make some points about it.
In assigning a method to a class, the basic idea is that, that method or behaviour really belongs to that class - it is really a property of that class or type. For example, breathing for Animal. When this is the case, the behaviour is tied to class state (or data, or attributes, or variables). If a method does not access the class variables in any ways, then, that method may not belong there. At least it is the general rule.
Now, in your case, you have m1(), m2(), ... methods that appear in two different classes. This raises the possibility that they may not be really tied to the state of those classes. If so, then the better solution is to completely remove them into a new class.
If you do so,
You will also get rid of two classes, A and C, which now exist only for this purpose.
You get rid of two inheritance relationships. This makes you code much simpler.
And, you will achieve your objective of not repeating your self.
--
//Parent classes (child classes are now gone)
public class B {}
public class D {}
--
// Your new class
public class X {
// methods that previously were in A and C
m1();
m2();
...
}
Although, I have mixed feelings about its use; you can use the include directive.
Create a file, like this, named sharedMethods.as (or whatever you want). This is not a real class; it just includes code snippets:
public var mySharedMethod(mySharedMethodArguments:ArgumentType):void{
// do something
}
Then you can include it in your your other classes:
public class A extends B {
include "sharedMethods.as";
}
public class C extends D {
include "sharedMethods.as";
}
The code from your include file will be compiled as part of Class A and Class C.
You could also put your shared code in another class and have an instance of that class in both A and C. Then you either have to write wrapper methods or drill down the calls sort of like this:aInstance.sharedCodeObject.sharedMethod();
My intuition is that if you run into this a lot; you may have a problem with the object model that needs some refactoring.
This might sound like a noob question.
class MyClass
{
public List<MyObjects> myObjects;
public MyClass()
{
//...
}
}
class UserClass
{
public void SomeFunction()
{
MyClass obj = new MyClass();
//Should this belong in constructor of MyClass?
obj.myObjects = new List<MyObjects>;
//Should 'SomeFunction' initialize obj.myObjects before using it, or
//should it assume it has been initialized and just use it?
obj.myObjects.Add(..);
}
}
Who is responsible for creation / initialization of MyClass.myObjects, when the default constructor is invoked?
Constructor of MyClass.
User of MyClass.
In general, the constructor of a class should do all work necessary for that class to be in a usable state. In your case here, you should probably provide an accessor method for myObjects. The principles of OOP say to encapsulate data. That means that myObjects should be private. You should only have access to it via accessor methods. By doing that, then you can construct the object and lazily create the list via the accessor method when it is actually needed.
Here is a wiki article dealing with Constructors. It mentions that a properly written constructor will leave the object in a valid state.
EDIT: Encapsulated myObjects with lazy initialization (Note I am assuming C# since your code sample looks kind of like that)
class MyClass
{
private List<MyObjects> myObjects;
public MyClass()
{
//...
}
public void Add(MyObject object)
{
MyObjects.Add(object);
}
private List<MyObjects> MyObjects
{
get
{
if (myObjects == null)
{
myObjects = new List<MyObject>();
}
return myObjects;
}
}
}
I have 3 simple classes:
public abstract class Container implements WritableComparable<Container> {} //empty
public class WeightedEdge extends Container { ... }
public class NodeWeightContainer extends Container { ... }
The Map phase was configured as such
JobConf createGraphPConf = new JobConf(new Configuration());
Job job = new Job(createGraphPConf);
...
createGraphPConf.setMapOutputValueClass(Container.class);
However I am receiving this error:
java.io.IOException: Type mismatch in value from map: expected org.hadoop.test.data.util.Container, recieved org.hadoop.test.data.WeightedEdge
at org.apache.hadoop.mapred.MapTask$MapOutputBuffer.collect(MapTask.java:1018)
at org.apache.hadoop.mapred.MapTask$OldOutputCollector.collect(MapTask.java:591)
at org.hadoop.test.map.CreateGPMap.map(CreateGPMap.java:33)
at org.hadoop.test.map.CreateGPMap.map(CreateGPMap.java:19)
at org.apache.hadoop.mapred.MapRunner.run(MapRunner.java:50)
at org.apache.hadoop.mapred.MapTask.runOldMapper(MapTask.java:435)
at org.apache.hadoop.mapred.MapTask.run(MapTask.java:371)
at org.apache.hadoop.mapred.LocalJobRunner$Job.run(LocalJobRunner.java:210)
Why I can't return a subclass of a class that was defined in the configuration? Is there a way around it? The problem is that my Map phase has to emit two distinct object types.
You can not return a subclass of a class that was defined in the configuration because Hadoop explicitly checks class type specified in setMapOutputValueClass and the type it receives from Mappers.
It does so because it needs to serialize/deserialize objects you emit from mappers. When it performs deserialization it creates new object of type that is specified in setMapOutputValueClass call and then uses methods of WriteableComparable interface to fill newly created object with data.
To be able to emit different object types you may define container non-abstract class and place actual object and its type identifier inside
public enum ELEM_TYPE { WE, WECONTAINER }
public class Container implements WritableComparable<Container>
{
ELEM_TYPE type; //actual element type -
// WeightedEdge or NodeWeightContainer
object value;
//WritableComparable implementation
// that casts value to the appropriate type
}
public class WeightedEdge { ... }
public class NodeWeightContainer { ... }
I faced the same problem today. There is a Writable class org.apache.hadoop.io.GenericWritable which can be used to address this problem. You need to extend the class and implement an abstract method:
public class Container extends GenericWritable {
private static Class[] CLASSES = {
WeightedEdge.class,
NodeWeightContainer.class,
};
protected Class[] getTypes() {
return CLASSES;
}
}
public class WeightedEdge implemets Writable {...}
public class NodeWeightContainer implements Writable {...}
Now you can use the class Container as the output value type of your mapper.
Important: Your actual map output classes (WeightedEdge and NodeWeightContainer) must implement the Writable interface.
Assume i have a costum actionscript class.
public class myClass
{
private var myVariable:ArrayCollection;
...
}
Suppose also that i have a different class, that changes a second variable, which has the metadatatag [Bindable]. What methods and events do i have to implement in either of these classes, to make myVariable change, whenever the other is changend?
If you make the myVariable public, then you can just use [BindingUtils.bindProperty()][1]:
public class MyClass
{
public var myVariable:ArrayCollection;
public function MyClass(other:OtherClass) {
BindingUtils.bindProperty(this, "myVariable", other, "propertyName");
}
}
If you prefer to keep myVariable private, then you can use [BindingUtils.bindSetter()][2]:
public class MyClass
{
private var myVariable:ArrayCollection;
public function MyClass(other:OtherClass) {
BindingUtils.bindSetter(
function(newVal:*):void {
this.myVariable = newVal;
}, other, "propertyName");
}
}
I know singleton class is not supporting in Flex.Because it does not access private constructor.
But i want to make a class is singleton class. Please anyone can explain with example.
Thanks,
Ravi
A singleton is a class of which only one instance will be created. This instance will be shared by all other code in the program.
A singleton in the strictest sense is not supported in ActionScript because a constructor cannot be marked private. Consequently, additional instances of the class could be created elsewhere in the program. With the following trick, you can ensure that the constructor is only called by the singleton class itself:
package {
public final class Singleton {
private static var instance:Singleton = new Singleton();
public function Singleton() {
if( Singleton.instance ) {
throw new Error(
"Singleton and can only be accessed through Singleton.getInstance()" );
}
}
public static function getInstance():Singleton {
return Singleton.instance;
}
}
}