I have a class with many extended subclasses:
class FirstImplementation extends Mother { [...]
class SecondImplementation extends Mother { [...]
class ThirdImplementation extends Mother { [...]
What I am trying to do is a simple and light way to know if two instances of Mother class have the same implementation:
Mother a = new FirstImplementation();
Mother b = new SecondImplementation();
Mother c = new FirstImplementation();
a.sameKindOf(b); // return false;
a.sameKindOf(c); // return true;
My idea is to set an integer ID field in each Mother instance, and just compare it in sameKindOf function:
public class Mother {
private final int ID;
protected Mother(int ID) {
this.ID = ID;
}
public int getID() {
return this.ID;
}
public boolean sameKindOf(Mother other) {
return this.ID == other.getID();
}
}
Every extension of Mother shall call Mother's constructor with a precise ID.
My question is: is there a way to automatically give a different ID each time I create a new extension, or do I have to do it myself, giving a different number in each constructor class?
If not, is there a simpler way to accomplish what I am trying to do?
If you are interested only in ID-style solution... Try to use the following mechanism:
In your Mother class declare protected static int childClassesNumber;. It will store the number of all unique childs were loaded:
class Mother {
protected static int childClassesNumber = 0;
private final int ID;
protected Mother(int ID) {
this.ID = ID;
}
public int getID() {
return this.ID;
}
public boolean sameKindOf(Mother other) {
return this.ID == other.getID();
}
}
Then, to assure each child gets unique ID, you should use something like this in each child (and this is not good):
class ChildOne extends Mother {
public static final int ID;
static {
ID = ++Mother.childClassesNumber;
}
public ChildOne() {
super(ID);
}
}
The ID will be given only at class loading stage (only one time)
And (for example) ChildTwo:
class ChildTwo extends Mother {
public static final int ID;
static {
ID = ++Mother.childClassesNumber;
}
public ChildTwo() {
super(ID);
}
}
After that, the following code
System.out.println(new ChildOne().sameKindOf(new ChildOne()));
System.out.println(new ChildOne().sameKindOf(new ChildTwo()));
gets:
true
false
This mechanism has a huge drawback - you should put the static initialization in each child. The boilerplate code and so on and so forth... so I would recommend you use #Ash solution )
Wouldnt
public boolean sameKindOf(Mother other) {
return this.getClass().equals(other.getClass());
}
do the job ?
Take a look at java.util.UUID class and its static factory method public static UUID nameUUIDFromBytes(byte[] name). Is that what you are looking for?
Related
Let's assume I have two objects, both created through the builder pattern and one is nested into other:
class Parent {
private final Child child;
private Parent(Child child) {
this.child = child;
}
public static class Builder {
private Child child;
public Builder() {}
public Builder child(Child child) {
this.child = child;
return this;
}
public Parent build() {
return new Parent(child);
}
}
}
class Child {
private final long id;
private Child(Builder builder) {
this.id = builder.id;
}
public static class Builder {
private long id;
public Builder() {}
public Builder id(long id) {
this.id = id;
return this;
}
public Parent build() {
return new Child(this);
}
}
}
So, the obvious usage is quite simple:
Person.Builder parentBuilder = new Person.Builder().child(new Child.Builder().id(10).build());
Is it quite common to make
public static class Builder {
private ChildBuilder child;
public Builder() {}
public Builder child(ChildBuilder child) {
this.child = child;
return this;
}
public Builder resetChildId() {
child.id(0);
return this;
}
public Parent build() {
Child childToPass = child.build();
return new Parent(childToPass);
}
}
That way it is still possible to update the child#id later, however due to late binding the errors are thrown lately during Parent.Builder#build() method.
I would pass a Child instance to Parent rather than a ChildBuilder instance.
If you wish to change Child properties afterwards then you can simply construct a new ChildBuilder from parentBuilder.child().
However, I'm concerned about the design when I see all those builders. DDD is all about the ubiquitous language and "builder" is certainly not part of it. Sometimes you have no choice to introduce technical concepts in the design, but I believe that you may be forgetting about other DDD building blocks that may help.
I have builders everywhere because I have to do validation for each
domain entity in the app. For example name for Parent not longer than
255, but for child not more than 1000. - Tahar Bakir (from the comments)
The rules you describe above may be encapsulated and enforce upon construction in domain concepts such as ParentName and ChildName that can be implemented as value objects.
Your Parent and Child classes can then work with those concepts rather than strings.
Hope this helps
the example on how to use it is in the main method, this will print
10
0
The parent class:
public class Parent {
private final Child child;
private Parent(Child child) {
this.child = child;
}
public Child getChild(){
return this.child;
}
public static class Builder {
private Child.Builder childBuilder;
public Builder() {}
public Builder child(Child.Builder childBuilder) {
this.childBuilder = childBuilder;
return this;
}
public void resetChildId() {
childBuilder = childBuilder.id(0);
}
public Parent build() {
return new Parent(childBuilder.build());
}
}
public static void main (String[] args){
Parent.Builder parentBuilder = new Parent.Builder().child(new Child.Builder().id(10));
System.out.println(parentBuilder.build().getChild().getId());
//Reset the sucker
parentBuilder.resetChildId();
System.out.println(parentBuilder.build().getChild().getId());
}
}
The child class:
class Child {
private final long id;
private Child(Builder builder) {
this.id = builder.id;
}
public long getId(){
return this.id;
}
public static class Builder {
private long id;
public Builder() {}
public Builder id(long id) {
this.id = id;
return this;
}
public Child build() {
return new Child(this);
}
}
}
I have a variable in x class .And I have another class called "Y" to access the variable. Will it change the value in X class, if the value is incremented in Y class?
Java uses pass by value but we can achieve what you are asking for by passing an object as an argument to a method like this:
public class ClassX {
public int classId;
public ClassX(int id) {
this.classId = id;
}
public void setId(int id) {
classId = id;
}
public int getId() {
return classId;
}
}
public class ClassY {
public static void main(String[] args) {
ClassX cx = new ClassX(100);
ClassY cy = new ClassY();
System.out.println("classId:"+cx.classId);
cy.modifyId(cx); // an object is passed as argument to a method
System.out.println("classId:"+cx.classId);
}
public void modifyId(ClassX classx) {
classx.setId(220);
}
}
Assuming you have it defined like
public int anInteger = 4;
Then yes, it would change.
These are the sorts of things best learned from experimentation, try various ways of structuring the classes, declaring the variable, and accessing it. See what happens.
Yes. All you need is to pass a reference to it to the other class.
I've an issue with my class ListFromFile<T> which extends ArrayList<T>.
In that class, i would like to make a method that finds an element by its id attribute and returns it.
The T could be an object from the classes Student, Teacher etc. All these classes have a equals method that tests the id.
My problem is that i can't use the equals method which test the id in ListFromFile.
Here is my code :
public class ListFromFile<T> extends ArrayList<T> implements Serializable {
public T getElement(int id) {
for ( T o : this ) {
if ( o.equals((int)id) ) {
return o;
}
}
return null;
}
}
Even if i specify in the equals method i'm working with an id which is an int, getElement() doesn't find the element ...
After some searches, it seems that i have to extend T by Student, Teacher etc., but how to extends multiples classes ?
Thank you
You should use an interface or an abstract class with a getId() method. Bind T to be a subtype of either the interface or the abstract class. Using an interface, it might look like this.
public interface ObjectWithId {
int getId();
}
public class Student implements ObjectWithId {
// ...
}
public class Teacher implements ObjectWithId {
// ...
}
public class ListFromFile<T extends ObjectWithId> extends ArrayList<T> {
public T getElement(int id) {
for ( T o : this ) {
if ( o.getId() == id ) {
return o;
}
}
return null;
}
}
Here is sample application which shows how you can solve this problem:
import java.io.Serializable;
import java.util.ArrayList;
public class test2 {
// define basic interface for all objects
interface ObjectWithID {
public int getId();
}
public static class Teacher implements ObjectWithID {
private final int id;
public Teacher(final int id) {
this.id = id;
}
#Override
public int getId() {
return this.id;
}
}
public static class Student implements ObjectWithID {
private final int id;
public Student(final int id) {
this.id = id;
}
#Override
public int getId() {
return this.id;
}
}
// note T extends syntax
public static class ListFromFile<T extends ObjectWithID> extends ArrayList<T> implements Serializable {
public T getElement(final int id) {
for (final T o : this)
if (o.getId() == id)
return o;
return null;
}
}
public static void main(final String[] args) {
final ListFromFile list = new ListFromFile<>();
list.add(new Teacher(1));
list.add(new Teacher(2));
list.add(new Teacher(3));
list.add(new Student(4));
list.add(new Student(5));
list.add(new Student(6));
System.out.println(list.getElement(1)); // print teacher
System.out.println(list.getElement(4)); // print student
}
}
I have two classes: one called Student and the other one called Course. I would like to make a simulation for a simple registration system.
My Student class part has the following form:
class Student
{
private String id,
private Course[] listOfCourses;
private int numCourse;
//accesing methods
public registration(Course course){
listOfCourses[numCourse]=course;
numCourse++;
}
public Course[] getCourse(){
return listOfCourses;
}
}
and the Course class has the following form:
class Course
{
String id, String courseName;
//constructor
//accesing methods
}
I would like that by pressing a buttom in a form made in Java Swing, to display the contents of the courses registered by one specific student into a jTable. I have tried the following, but with no results at all:
Student e=new Student();
Course d[]=new Course[4];
d=e.getCourses(); //to receive the array of Courses from the Student class
for (int i=0;i<d.length;i++){
jTable2.setValueAt(estLista[i].getName(), i, 0);
}
how I can do that? I mean there is a way in which I could get the contents of the array, that is stored in the Course class, into the ActionEvent of the button?
From the code you have provided I believe there atleast one reason why you are not getting the courses.. because it is not set in registration process:) (Also the syntax is not correct unless you have a registration class?) This might not be a complete solution but it corrects one of the problem
public void registration(Course course){
// listOfCourses[numCourse];
listOfCourses[numCourse]=course;
numCourse++;
}
Ok, it is not too clear for me yet, but I will put some code and tell me if it helps you.
Note: Not tested
For Student (sorry I prefer to use lists instead of arrays):
public class Student {
private String id;
private List<Course> takenCourses;
public void registration(Course course){
if (this.takenCourses != null) {
takenCourses.add(course);
} else {
System.err.println("an array has not been specified.");
}
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public List<Course> getTakenCourses() {
return takenCourses;
}
public void setTakenCourses(List<Course> takenCourses) {
this.takenCourses = takenCourses;
}
For course:
public class Course {
private String id;
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
For your UI, I just created a "simulation" of UI, I assume you have implemented something more complete... I assume you have intialized the components as global variables for your frame or panel or at least you have methods to get them.
public class UIHelper extends JFrame {
Student student = new Student();
JButton btnAction;
JTable myTable;
public UIHelper() {
//Methods for creating UI
//.
//.
//.
student.setId("stackoverflowed");
student.setTakenCourses(new ArrayList<Course>());
btnAction = new JButton("Action!");
//Methods of the JButton (...)
btnAction.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
//Now just process since student is a global variable (you can set it static as well) but it shouldn't be a good practice at all
for (Course course : student.getTakenCourses()) {
System.out.println(course.getName());
//Add the element to your table.
}
}
});
}
public static void main(String[] args) {
//Assume this is your UI
new UIHelper();
}
Hope I give you an idea, best regards.
I have two classes
public class PrepaidPackage {
private String name;
private String serviceClassID;
private boolean isTranferable;
public boolean isTranferable() {
return isTranferable;
}
public void setTranferable(boolean isTranferable) {
this.isTranferable = isTranferable;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getServiceClassID() {
return serviceClassID;
}
public void setServiceClassID(String serviceClassID) {
this.serviceClassID = serviceClassID;
}
}
other class is
public class PostpaidPackage {
private String name;
private boolean isTranferable;
public boolean isTranferable() {
return isTranferable;
}
public void setTranferable(boolean isTranferable) {
this.isTranferable = isTranferable;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
I want to create a factory class which on base of package type create relevant class. But if you look at above clasess they dont have same type of methods and variables. So please guide how create interface or abstract class for above class?
Now factory will return class name Package. Would i able to call methods which are not present in other class.
Updates
Please suggest if i break my package into two classes like
public abstract class MyPackage {
public abstract PackageSpec getSpec();
public abstract PackagePrepaidDetails getDetail();
}
Now common attributes will be in PackageSpec and prepaid stuff in packageDetails.
Its kind of abstract factory pattern.
public class PrepaidPackage extends MyPackage{
PackageSpec spec;
public Spec getSpec() {
spec = new PackageSpec();
spec.setTranferable(true)
spec.setName("abc");
return spec;
}
public PackagePrepaidDetails getDetails() {
details = new PackagePrepaidDetails ();
details.setServiceClassID(123)
return details;
}
}
public class PostpaidPackage extends MyPackage{
PackageSpec spec;
public Spec getSpec() {
spec = new PackageSpec();
spec.setTranferable(true)
spec.setName("abc");
return spec;
}
}
I recomment you to have an interface if you don't have already. You do not neccessarily need it, but it is a good practice if they are so similar:
public interface Package {
public boolean isTranferable();
public void setTranferable(boolean isTranferable);
public String getName();
public void setName(String name);
}
Then in your calling code, you have a Package from your factory and:
Package p = myFactory.nextPackage(); // or something
if (p instanceof PrepaidPackage) {
PrepaidPackage prepaid = (PrefpaidPackage)p;
// and do the thing you want
} else if (p instanceof PostpaidPackage) {
PostpaidPackage postpaid = (PostpaidPackage)p;
// amd do the other things
}
Thing you are recommended to llok into is the instanceof operator and type casting.
A quick fix, not an ideal one is to have an interface that represents all the methods in the Prepaid class and leave them unimplemented in the Postpaid. That will solve the problem in the short term. I would suggest that you have a relook of the classes and the usages to avoid unimplemented methods in the code.
Well for an abstract super class you have to group everything common to both :
public abstract class MyPackage { // not sure you can call a class just "Package"
private String name;
private boolean isTranferable;
public boolean isTranferable() {
return isTranferable;
}
public void setTranferable(boolean isTranferable) {
this.isTranferable = isTranferable;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
then both inherits from it (the first adds serviceClassID and the second nothing)
your factory function will return a MyPackage (or AbstractPackage, whatever), but to access the specific function you'll have to cast after an instanceof test.
Two possible design choices you can make:
Have the prepaid package extend
postpaid package and your factory
then returns objects of type
postpaid package, the code which
calls the factory is then
responsible for inspecting the type.
Have a package interface which
defines all of the methods and have
postpaid package define the methods
to throw an
UnsupportedOperationException (ala
the way collections defines some
operations as optional.) or return
some kind of sentinel value (i.e. null)
For either of the above you could add another method getType() which returns an enum of the various package types you wish to implement, and this could then be used in the code that accesses the factory objects to determine which methods are available.