Encapsulation over engineering - java

In the doJob() method, B is referenced through getter. I personally do not favor this idea and would prefer just b.execute() since I know for sure that getB() will never be modified.
I know that by doing this, would be moving away from encapsulation, but isn't encapsulating B object an overkill here?
class A{
private B b;
public void setB(B b){
this.b = b;
}
public B getB(){
return b;
}
public void doJob(){
getB().execute();
}
}

It really doesn't matter if you access B through its attribute or getter as long as the attribute remains private (so yes, calling getB() is an overkill, it certainly doesn't break any design pattern).

In this scenario it's probably overkill because it's a simple object. But what if there was lazy loading and your object looked like this..
class A{
private B b;
public void setB(B b){
this.b = b;
}
public B getB(){
this.b = this.b ?? new B();
return this.b;
}
public void doJob(){
getB().execute();
}
}
Then it's not overkill to access your private members via a property.
I don't know if this will help you, but if B is a dependency then your object should be setup like this where IB is the interface of the concrete object B. It's an inversion of control pattern to decouple the concrete object B from A. But this is overkill for simple object graphs as well
class A{
private IB b;
// Use inversion of control
public A(IB b){
this.b = b;
}
public IB getB(){
return this.b;
}
public void doJob(){
getB().execute();
}
}

You are minimizing risk by using the getter. What if it turns out the B was null in one use case or you need to initialize B because of a new requirement. This pattern allows you to update getB() without having to change anything else in A.
public B getB(){
if(b == null) {
b = getEntityManger().findB(); // or wherever you wanted to get B from
}
return b;
}

Providing accessor/mutator methods for a private member enables you to add error checking, change the storage of the member, and do other things internal to the class. How you access the member within the class is your choice.
If you discover you need to change the class internals later, then switching to the accessor/mutator can be done then. Certainly this simple example does not require the accessor (getter) method. But realize that a more complex case might benefit by using the getter.

That is ok only if you make the whole class, or at least make the setter and getter, final.
Otherwise this breaks:
class A2 extends A {
private B2 b;
#override
public void setB(B b){
this.b = new B2(b);
}
#override
public B getB(){
return b.toB();
}
}
Now calling the non-overriden doJob() will use wrong member variable.

Related

How to handle polymorphism without casting object?

class A{
int a;
public int getA(){
return a;
}
public void setA(int a){
this.a=a;
}
}
// Class B extending A class and add one additional variable
class B extends A{
int b;
public int getB(){
return b;
}
public void setB(int b){
this.b=b;
}
}
// this is the main class
class HelloWorld {
public static void main(String[] args) {
A aa;
if(runtime conditon) {
aa= new B();
aa.setA(3);
((B)aa).setB(4);
}
else{
aa= new A();
aa.setA(3);
}
}
}
How to design to solve the above problem without using casting?
sorry for asking the low-level question (I am new to java).
Since class B extends class A you can use a variable of type A to point to a variable of type B.
But if you want to use only one variable of type A (in your case aa) you cannot use a method of class B without casting the object.
Because you have to remember that when you use a variable (in your case type A) that points to a derived type use (in your case type B), you can only use the methods that are defined in class A, the rest are obscured. By casting the object to its true type you can use all of its methods.
Introduce another variable:
B bb= new B();
bb.setA(3);
bb.setB(4);
aa = bb;

Difference between the code with "this" and without it

I'm a beginner in Java programming and I'm having some problems to understand some concepts. I would like to know if both implementations are the same:
Code 1
public class MyThisTest {
private int a;
public MyThisTest(int a) {
this.a = a;
}
Code 2
public class MyThisTest {
private int a;
public MyThisTest(int b) {
a = b;
}
Yes, both are the same, let's see why:
First
public class MyThisTest {
private int a;
public MyThisTest(int a) {
this.a = a;
}
You are using this to refer the member variable a. The use of this is because by parameter there is another a variable. If you don't use this what variable will be assigned the value? The same as the parameter, so it doesn't take effect because it is 'auto-assign' the value.
Word this ensures tthe member variable is referenced. This is mostly used in constructors and getter/setters because the parameter name should be the same as the member variable name, so to handle the ambiguity this is used.
The second code
public class MyThisTest {
private int a;
public MyThisTest(int b) {
a = b;
}
Into constructor there is no ambiguity between variables, so this is not needed, but you can still use this and it works perfectly.
Yes both implementations are same. But I would highly recommend you to read about it in detail so that you don't make any future mistake. This answer goes in detail about when we should use this.
this keyword would be added by compiler.
Actually, if you write something like this
public class A {
private int a;
public A(int b) {
a = b;
}
}
Compile and then decompile it you can see the work of compiler
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
public class A {
private int a;
public A(int b) {
this.a = b;
}
}
So, i would say avoiding this is just a usage of some syntax sugar.

2 classes with a parameter in its constructor of the other class

Lets say I have class A and class B. Their constructor looks like this:
public A(B b) {this.b = b;}
public B(A a) {this.a = a;}
Both of them have an instance of the other class as an instance variable.
Is it possible to create instances of those classes without an instancevariable being null?
I want an instance of class A and an instance of class B. The instance of class A should add the instance of class B as its instance variable and and vice versa.
One of the classes, let's choose A, will need a method
public void setB(B b) {
this.b = b;
}
that can be called after A and B objects are instantiated.
Two classes are tightly coupled. If each class instance require the other one to initialize, then the class design need to be revised from the beginning. Instead, to archive the goal of one instance has the other, using setter would help in this case
class A {
private B b;
public A(B b) { this.b = b; }
}
class B {
private A a;
void setA(A a) { this.a = a; }
}
B b = new B();
A a = new A(b);
b.setA(a);

How hibernate change classes or object at run time

I was trying to understand how hibernate work in the sense that how putting #Entity on a class makes it a persistent class ?
i.e
#Entity
class A{
private int b;
public int getB(){
return b;
}
public void setB(int b){
this.b = b;
}
}
behaves like below written class at runtime
class A{
private int b;
public int getB(){
return (SQL code to fetch b from DB)
}
public void setB(int b){
(SQL code to set b in DB)(b);
}
}
If we say it is using reflection then how it is changing the code that is inside the methods ?
Hibernate proxied / runtime-weave your class. Meaning when other classes invoke methods of your class, it doesn't invoke it directly, but it invokes the proxy. This proxy then contains logic that involves persistence context operations.
Have a look at library such as cglib or aspectj if you want to delve deeper in this topic (not necessarily the ones used by hibernate)

Java design, how do I avoid passing object down the hierarchy?!? Impossible?

I have a number of classes, please allow me to introduce them and then ask my question at the end:
I have a container class which contains two objects in a composite relationship:
public class Container{
A a;
B b;
public someMethod(){
a.getC().myMethod(b);
}
}
A and B are superclasses (or Interfaces), with subtypes that can also be the type held in the composite relationship.
A contains a member of (interface) type C:
public class A{
C c;
}
public interface C{
public void myMethod(B b);
}
public class D implements C{
public void myMethod(B b){
//This code will modify the state of object b, in class Container.
b.changeState();
}
}
public class E implements C{
public void myMethod(B b){
//This code will modify the state of object b, in class Container.
b.changeState();
}
}
My problem is that I wish to modify the state of object b from a method starting in the container class, which eventually calls code down the hierarchy, to classes D and E- calling myMethod() via dynamic binding. I want to do this because I am going to use polymorphism to run the correct myMethod() (depending on whether the type of object is D or E) and I wish to do this, rather than write IF statements.
So my problem is that it seems very bad continually passing the instance of object b down the class hierarchy to myMethod, so that I can run b-specific code to modify the state of b. Is there anything else I can do to modify b from d and e (collectively known as c)?
I can get this to work using just interfaces but without using generics- but when I added generics i had problems with types and that made me start to think if my whole design was flawed?
EDIT: I could probably do this easily just by using IF statements- but I wanted an elegant solution using polymorphism of classes D and E.
First of all, if I understood your question correctly, no instance of B is being "passed down" in your code. Dynamic dispatch will simply cause the myMethod() implementation in the actual type of a to be called with an instance of B as argument.
While it may be tedious to have to write the argument explicitly every time you implement myMethod(), there's nothing wrong with it.
The alternative is to give each subclass/implementation of A an attribute of type B. In this case, however, you would have to pass your B instance down the chain of constructors to the class that actually has your B attribute.
Your code would become:
public class A{
C c;
public A(C c) {
this.c = c;
}
public interface C{
public void myMethod(B b);
}
public abstract class CC {
protected B b;
public CC(B b) {
this.b = b;
public class D extends CC implements C {
public D(B b) {
super(b);
}
public void myMethod(){
b.changeState();
}
}
public class E extends CC implements C {
public E(B b) {
super(b);
}
public void myMethod(){
b.changeState();
}
}
And then somewhere, e.g. in Container's constructor:
b = new B();
a = new A(new E(b));
You could pass the instance of B to the constructor of E. (or use a setter). That poses issues in itself, but at least it avoids having to pass B down every time you call myMethod(), which now needs no arguments.
e.g.
somewhere inside B
E myE = new E(this);
and, inside E
final B myB;
public E(B myHigherLevelThing) {
this.myB = myHigherLevelThing;
}
public void myMethod() {
myB.changeState();
}
Use the most general interface for the declarations, I'm a little confused about your full hierarchy so there may be room for improvement there...

Categories

Resources