I'm currently taking a Java course and have a question about polymorphism.
Given
public class A {
private int a1;
public A(){}
public A(int a1) { this.a1 = a1;}
}
class B extends A {
private int b1;
public B() {}
public B(int b1, int a1) {
super(a1);
this.b1 = b1;
}
}
class C extends B {
private int c1;
public C(){}
public C(int c1, int b1, int a1) {
super(b1, a1);
this.c1 = c1;
}
}
What would be the best way to assign to fields a1, b1, and c1, all in one swoop? My first guess would be to make an instance of C and call its three-arg constructor.
But what happens when each class contains 10s or 100s of data fields? Wouldn't this approach mean calling constructors with huge numbers of arguments, like
C(arg1, arg2, ..., arg100), setting k of C's fields, then making a call to
B(arg1, arg2, ..., arg100-k), and so on,
all the way up to the top? Is there a better way to proceed?
Having so many parameters is a definite code smell; in all probability you want to split the object up into smaller self-contained objects and/or or collections.
On the other hand, there is the Builder pattern, where you use a helper class to set all the parameters and it constructs the object for you, possibly sanity-checking that all required fields are set and there are no conflicts.
Not in this particular case because the fields in the parent classes are declared private.
If they were protected then you could set all 3 of them from the class C constructor. However this breaks encapsulation because if the constructor for B did something else after the value was assigned you'd have to duplicate that logic in C in order to not violate it's contract, and as you can imagine that gets very messy when you have more constructors or parent classes in the type tree.
Having multiple calls chained in the manner you proposed is the safest way at the cost of having to call all those constructors up the chain. I'd recommend profiling your code to see if this is actually a problem and not just a premature optimization.
What you're suggesting would work if you set the class fields to public. Class C will have a1 and c1, but won't be able to access them due to them being private.
Related
This question already has answers here:
Managing constructors with many parameters in Java
(8 answers)
Closed 6 years ago.
Assume that I have some subclasses that extend a superclass. These subclasses differ by the parameters passed to the superclass. Unfortunately, like the following example, I can end up with "many" parameters. Is there a general method of avoiding this? Are constructors with "many" arguments considered good practice? Would it be better to have getter/setter methods instead of passing every parameter via constructor?
public abstract class SuperClass {
private int a;
private int b;
.
.
private int z;
public SuperClass(int a, int b, ... int z) {
this.a = a;
this.b = b;
.
.
this.z = z;
}
}
public class SubClass1 extends SuperClass {
public SubClass1() {
super(4, 3, ..., 9);
}
}
public class SubClass2 extends SuperClass {
public SubClass2() {
super(1, 7, ..., 2);
}
}
If your subclasses vary only in the parameters passed to the superclass, you might be looking for the Builder Pattern. A builder for the superclass lets you pass in whatever parameters you need without cluttering your constructor, and if you want subclasses for readability, you can just wrap a call to the builder and return its result from the subclass constructors.
Generally, constructors with many parameters is a code smell. It means you probably have a class that breaks the "Single Responsibility Principle". If you can't avoid it, try using the builder pattern!
I would not have constructors in my classes as the behavior of the objects instantiated by each constructor may be different and hard to determine.
One thing to check is: should SuperClass be split into simpler classes?
If this can't be done: if you have too many parameters then you can have a special class that holds the parameters; with setters and getters for each parameter.
One can fill the values in from property files, so you can have profiles for common cases.
class SuperClassParam
{
void seta(int a);
int geta();
//...
}
class SuperClass
{
public SuperClass( SuperClassParam params )
{
}
If the number of parameters can vary, then use a variable arity ("varargs") parameter. Declare an array instead of all those other instance variables. The variable arity parameter is typed as an array when in the method.
private int[] all;
public SuperClass(int... all) {
this.all = all;
}
Your subclass constructors will not have to change at all.
I have a calculation in an actionPerformed() method in class A. The results are two arrays containing doubles C[] and D[]. How can I send it to another class B?
There any number of ways you could achieve this.
The important parts are:
Have a reference to B
Have some kind of means for B to receive the values you want to send. I'd recommend a setter method of some kind
You could also use a common model, which is essentially the same, but exposes less about B to A making it more difficult for A to do naughty things to B it probably shouldn't ;)
Create an instance of class B and pass the result of the calculation to that instance.
This is a very basic problem and is easy to solve once you've had some experience. You might find the wiki on Object-oriented programming useful. Its powerful stuff once you understand it.
Here's some examples for you...
public class ClassB{
double multiplier;
public ClassB(){
//this will be called when you create an instance of class B
//with no arguments. Also called the default constructor, or empty-arg
//constructor.
multiplier = 2;
}
public void setMultiplier(double value){
multiplier = value;
}
public void calculate(double[] c, double[] d){
//do nifty stuff, like multiply every value in c and d!
for(int i=0;i<c.length;i++){
c[i] *= multiplier;
d[i] *= multiplier;
}
}
}
// and in your class having the action performed method...
//create an instance of class b. This will call the empty-arg constructor.
ClassB classB1 = new ClassB();
ClassB classB2 = new ClassB();
public void actionPerformed(ActionEvent e){
double[] c1 = new double[10];
double[] d1 = new double[10];
double[] c2 = new double[10];
double[] d2 = new double[10];
//call classB1 calculate method. This will multiply c1 and d1 by 2,
//as classb1's multiplier is 2.
classB1.calculate(c1, d1);
classB2.setMultiplier(4);
//call classB2 calculate method. This will multiply c2 and d2 by 4,
//as classb2's multipler has been set to 4.
classB2.calculate(c2, d2);
}
This is just a simple example of what object oriented programming can do for you. There's a ton more to learn than this, but as you're obviously just beginning I won't overwhelm you.
Try making both arrays C & D static. Making these static will allow other classes access to it. Otherwise, you should pass it through a parameter to the constructor.
Parameter Method:
public class A implements ActionListener{
Array C;
Array D;
Bclass B = new Bclass(C, D);
public void actionPerformed(){
//Do stuff to Arrays
}
}
public class Bclass{
Bclass(Array C, Array D){
//This is Constructor...
}
}
Static Method:
public class A implements ActionListener{
public static Array C;
public static Array D;
public void actionPerformed(){
//Do stuff to Arrays
}
}
public class Bclass{
Bclass(){
//This is Constructor...
A.C().getIndexOf("C-stuff");
A.D().getIndexOf("D-stuff");
}
}
You have tons of ways. The correct one for you depends on the structure of object model you use.
However, there are two basic concept you have to understand:
1. What is the "intersection point".
In order for A's instance (call it a1) to be able to communicate with B's instance (b1), a1 must have a way to "put his hands" on a reference to b1. A few example ways to do it are:
Each A get's a reference to B's instance as an argument to it's constructor, or another 'set' method, and then stores it as a field made for that purpose.
a1 and b1 share a common instance of class C. c can be the 'parent' of both a1 and b1 (i.e. contain both of them), or some 'manager' component that manage a certain process in your program.
The static \ singleton way. B class stores a static instance of itself, which allows reference to it from everywhere in the program.
2. What is the the desired communication interface
The interface one class exposes to others should be well designed in order to achieve many important concepts, e.g.: readability of code, security and 'hiding', reliability etc. This also depends on if both A and B are stored in the same package or are internal classes of each other or are even inherited from each other.
A few standard ways to communicate are:
Direct writing access: a field in B is publicly exposed and allows direct writing into it. this is mostly a bad behavior (a rule of thumb is that all fields should be at least protected if not private).
set methods: B has a set method that receives the calculated data, process it and stores it in it's fields (or pass it on).
Listening - A stores the calculated data in itself, and lets all of it's registered "listeners" know that a new data is available by calling an appropriate method in them. The listeners have read access to the relevant fields, or the data is passed as an argument, and then the listener (b1) decides what to do with the data.
I'm not that good OO design .. so please bear with me..
I have Class A, And 2 classes which extend A. But both of them have same fields.. So what is better, to have getter / setters in A or to have same getter / setters in both child classes.. Or is there a better a way to do this..?
this is what i have done (mock)..
class A{
private int x;
protected A(int x){
this.x = x;
}
public static A createA(id a, int x){
switch(a){
case 0:
return new C(x);
break;
//so on
}
public int getX(){
return x;
}
}
Thanks..
This depends on the classes
If those properties are a property of A then yes,
if it's just chance they have the same properties then no.
Basicly the question you need to ask yourself is, will there ever be a class that extends A that doesn't need those properties.
If the answer is no, put them on A,
If the answer is yes, keep them on the sub-classes,
or create another abstract class in between those 2 subclasses, having these 2 properties.
Let's say your classes are A (the parent) and B and C (the children). You say that B and C have some fields that are the same.
Ask yourself: If you had another class D, child of A, would it have those fields too regardless of its specific functionality?
If the answer is yes, then the existence of these fields in both subclasses is definitely not a coincidence, so you should probably define them in A, because it means that they have these members precisely because they inherit from A.
If the answer is no, the existence of these fields in the subclasses may or may not be a coincidence. So, you should ask yourself: Even if D doesn't have these fields, does their existence in both B and C look more than just a coincidence? Do these classes share something that D, another child of A, simply doesn't happen to share?
If yes, then consider a new class E that extends A, with E defining these common members and then make B and C children of E instead of A.
If not (if it looks to you like just a coincidence), then leave your structure as it is. Or consider an interface instead.
I got a class Foo having a method doSomething that uses two class-related variables b and c that are expensive to get/create. My first version looks like this:
public class Foo {
private final A a;
public Foo(A a) {
this.a = a;
}
public void doSomething() {
final B b = a.getB();
final C c = b.getC();
for (int i = 0; i < 1000; i++) {
// do something with b and c
}
}
}
So I get the first object (type B) via a class variable a and the second object (type C) via the first object.
Now, since those variables are related to the class and the method is always called exactly one time (though not necessarily when creating an object of type Foo), I thought about making them class variables as well:
public class Foo {
private final A a;
private final B b;
private final C c;
public Foo(A a) {
this.a = a;
b = a.getB();
c = b.getC();
}
public void doSomething() {
for (int i = 0; i < 1000; i++) {
// do something with b and c
}
}
}
I'm not sure which version to use if any of those two. I somehow don't feel comfortable making those two variables class members since they can be retrieved from the existing class variable a. However, it would increase readability of the methods IMO.
You are absolutely right. If it increases readability, bu all means do it. However, I would ask you this: What is the purpose of Referencing A from within the class? Is it only for getting B and C?
In this case, I would just input B and C in Foo's constructor!
This way you even make it more readable by breaking the dependency on A and Making the dependency on B and C more explicit.
Also, consider whether you are using these variables in other methods in the class. If the answer is yes- it signals that they should be class members, However, if the class contains a lot of methods that do not use these variables, that might signal the opposite.
The general principle you should follow here is the principle of High Cohesion
generally speaking, if you can use a local variable, it is preferable to using a field.
Using a local variable
limits the variable to where it is used.
uses less memory.
is thread safe.
Why not just store instances of B and C in your class Foo? Do you reference A somewhere in your class? Otherwise, Storing both B and C as instance variables is no less memory efficient, since storing one A object contains a B and C object.
From my experience static (or class variable|field|method) usually became evil after some time and needs to be refactorred out except cases when this stuff is static by it's nature (Math.PI or Math.max() are examples or such static things). If those methods are doing some computation based on anything dynamic I would leave them as instance.
I want to know about the advantage in between the creating an object for sub class but assigning class A ref instead of assigning Class B ref. which is shown in line1,line2 below code
class A
{
int b=10;
}
class B extends A
{
int b=12;
}
class Test
{
public static void main(String[] args)
{
A a=new B(); //line1
//B a=new B();//line2
System.our.println(a.b);
}
}
If you're not going to need any methods specific to B, in other words, you're strictly going to use it as an A, it's an advantage for readability to state so.
But the main advantage comes to light when you use the general type in a method declaration:
public String resolveName(A a) { ... }
If you used B here for no good reason, then you would unnecessarily cripple your method. It could have worked for any A, but it works only for B.
try reading this: Polymorphism
In your short example there's no real advantage,.
But in general your question is about what polymorphism is good for?
And the answer goes back to the need of OOP methodology.
In short it gives you the ability to encapsulate and abstract the implementation from the usage, and can help you I the future to replace the implementation without a need to change the usage.
For more details see http://en.wikipedia.org/wiki/Polymorphism_(computer_science)
In that example, I don't think you can talk about an advantage (or disadvantage), because your two lines of code each do something very different.
If the type of variable a is A, then a.b refers to the field b with the value 10.
But if you change the type of a to B then a.b refers to a totally different field, the one declared inside B, with the value 12.
If instead b was a method, then the one declared in B would "override" the one declared in A, which is a very different situation. e.g.
class A
{
public int b() { return 10; };
}
class B extends A
{
public int b() { return 12; }
}
And the calling code would be:
A a=new B(); //line1
//B a=new B();//line2
System.our.println(a.b());
That is, we call the method b to get the return value. Now it makes no difference to the behaviour whether the type of a is A or B. What matters is the type of object that a refers to, which is always B and hence always has the behaviour defined in B, so it will print 12 regardless.
The advantage of this is that you can have a collection of objects (e.g. various kinds of vehicle) and they can be a mixture of cars, boats, trains etc. Each has its own implementation of the start method, so you can treat them all the same way.
Although generally it's clearer to define such methods in an interface, rather than a class. There is no general way to start a vehicle, so no reason to have a base class that has a meaningless implementation of start. Instead you just use an interface to declare the "shape" of the method without giving it any implementation.