Cleaner way of using inheritance to separate 'static' code from 'dynamic' code - java

(With static and dynamic I mean the distinction whether code is susceptible to change)
I have a bit of a weird problem I'm currently stuck on. I'm writing an application which involves some complex interactions between components in which it becomes hard to keep track of the code flow. To simplify this, I'm trying to structure the code by creating 'layers', where each layer has increased functionality compared to the layer above it. Each layer is contained in a package. I'm having the following problem:
Consider the following 2 classes and their subclasses with increased functionality:
Class A:
package layer;
class A {
B b;
A() {
b = new B();
}
void foo() {
b.foo();
}
/* More A-class methods here */
}
Class B:
package layer;
class B {
void foo() {
// Do something
}
/* More B-class methods here */
}
Subclass A:
package sublayer;
class ASub extends A {
ASub() {
super.b = new BSub(); // This needs a cast to compile
}
}
Subclass B:
package sublayer;
class BSub extends B {
#Override
void foo() {
// Do something with more functionality
}
}
In the end I just want to instantiate and modify classes ASub and BSub, being able to use all methods of superclasses A and B without actually needing to modify code in classes A and B itself.
If I call new ASub().foo(), I want the overridden foo() of BSub to execute instead of that of B. Ofcourse I can add a variable BSub bsub in ASub and override A's foo() method to call bsub.foo(), but this doesnt avoid the creation of the object b in the constructor of A, which seems sloppy coding. Any thoughts on this? Any comments are welcome.

Your question is a bit controversial. Object creation and dependency injection is the subject of a lot of discussion and a core focus of various frameworks and design patterns.
But here is, I hope, one simple answer to your question, which isn't a general "what's the best way to create objects in Java?"
In the code below, I move the responsibility of instantiating B to a method (instantiateB()) which is called from the A (superclass) constructor. So, when you want to subclass A, you override that method instead of overriding the constructor.
package com.matt.tester;
public class SE {
static class A {
B b;
A() {
instantiateB();
}
void instantiateB () {
this.b = new B();
}
void foo() {
b.foo();
}
/* More A-class methods here */
}
static class B {
void foo() {
System.out.println("Hellow from B.foo()!");
}
/* More B-class methods here */
}
static class ASub extends A {
#Override
void instantiateB() {
this.b = new BSub();
}
}
static class BSub extends B {
#Override
void foo() {
System.out.println("Hellow from BSub.foo()!");
}
}
public static void main(String[] args) {
A a = new ASub();
a.foo();
}
}

Using inheritance to promote reusability is a really really bad idea. The inheritance should be always driven by the nature of the objects that you are trying to describe. You need to learn yourself to work with terms and abstractions to ask yourself "What is the nature of what I am trying to describe". My suggestion is to learn a book on Domain Driven Design for example or Code Complete. Also think about polymorphism and design patterns.

Related

Can this code be considered for member overriding in Java?

Java, in theory, doesn't support member overriding so I was thinking whether this code snippet can be used for overriding members of the class. However, I am not quite sure in what situations this code might fail. I mean, if this works perfectly then it wouldn't go unnoticed right?
It might be a stupid question, but I really want to know what this code might do in different situations which my mind can't think of.
So it will be really great if someone can explain it to me.
Thanks!
class ClassA{
int i = 10;
void eat() {
System.out.println("In Class A: Eating");
}
void bark() {
System.out.println("In Class A: Barking");
}
}
class ClassB extends ClassA{
//int i = 20;
ClassB(){
super.i = 20; //Changing the value of i in class A.
}
void eat() {
System.out.println("In Class B: Eating");
}
}
public class Main{
public static void main(String[] args) {
ClassB b = new ClassB();
System.out.println(b.i);
b.eat();
b.bark();
ClassA ua = new ClassB();
System.out.println(ua.i);
ua.eat();
ua.bark();
ClassA a = new ClassA();
System.out.println(a.i);
}
}
I am not quite sure in what situations this code might fail.
It (sort of) fails on the human reader/conceptual level.
The java language is what it is. This means that java programmers know what to expect, what to do, and what not to do.
And one of the basic rules for inheritance (in java, but also in general): you are extremely cautious regarding fields of your super class(es). Member fields should be considered an internal implementation detail of a class. You don't expose it to the outer world. You don't expose it to your child classes, unless there is a really good reason to do so. And if you really want to do that in java, then the correct way is: using the protected keyword for that field.
Your idea is basically that the child class "knows" about super class fields, and worse: changes that "internal state" at creation time.
Thus, in the real world, such code might quickly lead to all sorts of nasty surprises. Because people in the real world wouldn't expect that a subclass is doing something like, thus they might be really surprised to find "i should be 10, why is it 20" when debugging a problem in a large application.
Long story short: the fact that you can do something doesn't mean that you should do it. To the contrary: good programming is about doing things in "standard" ways that do not surprise your readers.
If you override a method then try to call it from the parent, the parent calls the derived method, even though it wasn't aware of it at definition time.
class A {
public void foo() {
System.out.println("A.foo");
}
public void callFoo() {
this.foo();
}
}
class B {
public void foo() {
System.out.println("B.foo");
}
}
B instance = new B();
instance.callFoo(); // Prints "B.foo"
Now if we try to do the same thing with instance fields, we get the original one.
class A {
public String foo = "A.foo";
public void printFoo() {
System.out.println(this.foo);
}
}
class B {
public String foo = "B.foo";
}
B instance = new B();
instance.printFoo(); // Prints "A.foo"
So we haven't actually overridden anything; we've simply made a new variable that happens to confusingly share the name of an existing one. If it was true overriding, then we would be able to augment the behavior of A methods which use that variable but aren't aware of the subclass.
Simple answer for your question is 'Yes', your eat method of class ClassA is overriding in class ClassB. The easy option to verify, is using #Override annotation.
In a subclass, you can override and overload an instance method. Override means, you are subclass replacing the inherited behavior. Overloading means, you are extending the inherited method.
If you modify your ClassB as follows , it will compile successfully.
class ClassB extends ClassA{
//int i = 20;
ClassB(){
super.i = 20; //Changing the value of i in class A.
}
#Override // **Added line is here**
void eat() {
System.out.println("In Class B: Eating");
}

Constructor injection to a class consisting of only static methods?

I am working on an API which interface with a proprietary piece of hardware. In this API, I have constructed a utility class (for the sake of this post let's call it B), consisting of only static methods. Most of these methods depend on another class for communicating with the hardware, let's call this A. I am currently a little unsure how to design the dependency of B on A as I cannot instantiate B and inject the dependency using constructor injection. From a design perspective, what is the best way to model this behavior?
For a little more hands-on description, here is what I am trying to achieve. Let's say A has declarations of certain other classes like so
class A
{
private HardwareCommunicator communicator;
private ModelLoader modelLoader;
public HardwareCommunicator getCommunicator()
{
return communicator;
}
public ModelLoader getModelLoader()
{
return modelLoader;
}
}
And B then has static methods like so, which seek to use some of the members declared in A
class B
{
public static PerformOperation()
{
AnotherClass c = new AnotherClass();
c.someMethod(someValue, hardwareCommunicator.getCommunicator()); // Needs reference
}
}
Obviously, B needs a reference to A, so I am currently fiddling with passing the dependency as an argument to the method, like this:
class B
{
public static PerformOperation(HardwareCommunicator communicator) // Passed as argument
{
AnotherClass c = new AnotherClass();
c.someMethod(someValue, communicator.doSomething()); // OK, so far so good
}
}
Now I run into the problem that I sometimes need more dependecies than just the communicator in B, e.g. in another static method in B I might need both the HardwareCommunicator and the ModelLoader
class B
{
public static SomeOtherOperation(HardwareCommunicator communicator)
{
AnotherClass c = new AnotherClass();
c.SomeMethod(someValue, communicator.doSomething(),
ModelLoader.getModelLoader()); // Missing reference
}
}
OK, so I could just pass this as a parameter as well, but now I am thinking I have an architectural problem. I should (shouldn't I?) be able to just go
class B
{
public static SomeOtherOperation()
{
AnotherClass c = new AnotherClass();
c.someMethod(someValue, instanceOfA.getCommunicator(),
instanceOfA.getModelLoader());
}
}
Without being able to call a constructor on B and pass in an instance of A I obviously can't achieve this behavior.
What am I missing? Thank you.

Return a private class implementing an interface keeping the implementation private

Static method M returns an object implementing interface A:
interface A { ... }
static A M() { ... }
Within M I would like to construct an object of type B and return that, given that B implements A:
class B implements A { ... }
I do not want client code to know anything about how B is implemented, I would prefer for B not to be a static class, B must be immutable and there could be different B handed to different clients. I want to prevent instantiation of B outside method M at all costs (short of reflection, as one user commented).
How can I achieve the above? Where and how should I implement B? Could you please provide a short code example?
My main problem is: how can I have "different Bs?"
A static inner class is probably your best bet. You won't be able to "prevent instantiation of B at all costs" since with reflection, client code can bypass all access modifiers.
You can use anonymous inner class that won't be called B (is anonymous) but will implement A for example
interface A {
void someMethod();
}
public class Test {
static A M() {
return new A() {// it will create and return object of anonymous
// class that implements A
#Override
public void someMethod() {
}
};
}
}
Without using reflection object of anonymous class can be created only by method M. Also it can't be extended so it is good first step to immutability.
You could also use a Proxy implementation to hide the implementation class further
public interface A {
public Object getValue();
}
public class Factory {
public static A newInstance() {
return new ProxyA(AImpl);
}
}
public class ProxyA implements A {
private A proxy;
public ProxyA(A proxy) {
this.proxy = proxy;
}
public Object getValue() {
return proxy.getValue();
}
}
All this is really doing is hiding the implementation of A under another layout and makes it difficult to create a instance of ProxyA
But as #Asaph points out, with reflection, it becomes next to near impossible to truly guard against people accessing various parts of the classes and objects...
You could also separate your interface and implementations via different Classloaders, so that you only ever expose the interface's to the developers and implementations are delivered by dynamic class loading them at runtime. While not solving the underlying problem, it further complicates the matters for those trying to circumvent your factory.
IMHO

Non-static create-new-from method?

I sometimes write classes which can be converted to- and from- something else, and I'm used to writing it as a non-static convert-to method and a static convert-from method, for example:
class A {
B toB() {...}
static A fromB(B b) {...}
}
or
class B {
void save(File f) {...}
static B load(File f) {...}
}
I used to think it's a good and simple approach, but lately the static-ness of the conversion-from method has been annoying me, for instance if I want to define an interface for types that can be converted to- and from- B:
interface ConvertableToAndFromB {
B toB();
// ?
}
So, is there an elegant way of doing that without having the conversion-from as static, other than migrating to Smalltalk?
EDIT
To clarify, I realize I can add a non-static method in the interface, e.g.:
interface ConvertableToAndFromB {
B toB();
void fromB(B b);
}
or, if I want to allow immutable types (thanks Stripling):
interface ConvertableToAndFromB<T implements ConvertibleToAndFromB<T>> {
B toB();
T fromB(B b);
}
But that will require me to create a new A before I can even invoke this, as in:
A a = new A();
a.fromB(b);
or (for immutable):
A a = new A();
a = a.fromB(b);
which is what I'm trying to avoid (but will do with no other solution). I just hope there's a nicer way.
You should be able to make your interface recursively generic. I believe the syntax is like this:
interface ConvertibleToAndFromB<T implements ConvertibleToAndFromB<T>>{
B toB();
T fromB(B b);
}
class A implements ConvertibleToAndFromB<A> {
B toB() {...}
A fromB(B b);
}
Making things more strongly typed like this has obvious advantages. However, it does mean that you have to be somewhat aware of the actual type that you want when you call fromB. There are advantages and disadvantages to this approach.
As a side note, making A responsible for generating objects of type A or B violates the Single Responsibility Principle, and I would generally prefer to have a separate Converter class or interface to perform these actions.
Converter<A, B> converter = converterFactory.get<A, B>(A.class, B.class);
B b = converter.from(a);
Often, a fromB method would be implemented as a copy constructor. E.g.
public class A
{
public A(B b)
{
this.someValue = b.someOtherVariable;
}
}
Unfortunately this does not help you create an interface to abstract said functionality. Normally, a separate factory could be used, and this factory implement an interface, but this would still not allow you to get around being able to implement the method in your object in a non-static way while avoiding unnecessary instantiation.
In your scenario, I'll do it this way:
interface ConvertableToA {
A toA() {...}
}
interface ConvertableFromA {
Object fromA(A a) {...}
}
class MyConvertableClass implements ConvertableToA, ConvertableFromA {
...
}
creating a utility helper class might be better because if you think about it, conversation has nothing to do with the object/instance.
for example, when you convert an array to list, you don't do arr.asList(), rather, you use Arrays.asList(arr)

Why can't java find my method?

I am trying to wrap my mind around something in java. When I pass an object to another class' method, can I not just call any methods inherent to that object class?
What is the reason code such as the example below does not compile?
Thank you,
class a {
public static void myMethod(Object myObj) {
myObj.testing();
}
}
class b {
public void testing() {
System.out.println ("TESTING!!!");
}
}
class c {
public static void main (String[] args) {
b myB = new b();
a.myMethod(myB);
}
}
Edit: The reason I have left the parameter in myMethod as type Object, is because I would like to be able to pass in a variety of object types, each having a testing() method.
If you would like to pass in a variety of objects with testing() methods, have each object implement a Testable interface:
public interface Testable
{
public void testing()
}
Then have myMethod() take a Testable.
public static void myMethod(Testable testable)
{
testable.testing();
}
Edit: To clarify, implementing an interface means that the class is guaranteed to have the method, but the method can do whatever it wants. So I could have two classes whose testing() methods do different things.
public class AClass implements Testable
{
public void testing()
{
System.out.println("Hello world");
}
}
public class BClass implements Testable
{
public void testing()
{
System.out.println("Hello underworld");
}
}
The problem is that myMethod can't know it's getting a b object until it actually runs. You could pass a String in, for all it knows.
Change it to
public static void myMethod(b myObj) {
myObj.testing();
}
and it should work.
Update of the question:
Edit: The reason I have left the parameter in myMethod as type Object, is because I would like to be able to pass in a variety of object types, each having a testing() method.
As Amanda S and several others have said, this is a perfect case for an interface. The way to do this is to create an interface which defines the testing() method and change myMethod to take objects implementing that interface.
An alternative solution (without interfaces) would be to reflectively discover if the object has a testing() method and call it, but this is not recommended and not needed for a such a simple case.
What you are talking about is duck typing. Java doesn't have duck typing.
Therefore you need to define an interface that all the classes with a testing() method implement.
e.g:
public interface Testable
{
public void testing()
}
class B implements Testable
{
public void testing() {
System.out.println ("TESTING!!!");
}
}
class A {
public static void myMethod(Testable myObj) {
myObj.testing();
}
}
Your issue is a classic argument in favor of an interface. You want as generic as possible, yet you want every object you pass to have a testing() method. I suggest something along the lines of the following:
public interface Testable
{
public void testing();
}
public class A
{
public static void myMethod(Testable myObj)
{
myObj.testing();
}
}
public class B implements Testable
{
public void testing()
{
System.out.println("This is class B");
}
}
public class C implements Testable
{
public void testing()
{
System.out.println("This is class C");
}
}
public class Test
{
public static void main (String[] args)
{
B myB = new B();
C myC = new C();
A.myMethod(myB); // "This is class B"
A.myMethod(myC); // "This is class C"
}
}
Because you're passing in an Object (b inherit from Object). Object doesn't have testing, b does.
You can either pass in b or cast the object to b before calling the method.
EDIT
To pass in a generic class that implements that method: you'll want to make an interface that has the method signature and pass in the interface type instead of Object. All objects that you pass in must implement the interface.
You can only access the members that are visible for the type of reference you have to the object.
In the case of myMethod(Object myObj) that means only the members defined in Object, so in class a the members of class b will not be visible.
If you changed the definition of a.myMethod to be public static void myMethod(b myObj) you would then be able to see the testing method on the instance of b while in myMethod.
update based on clarification:
In that case defining an interface for all of them to implement is likely what you want.
public interface Testable {
public void testing();
}
public class a {
public static void myMethod(Testable myObj) {
myObj.testing();
}
}
public class b implements Testable {
public void testing () {
System.out.println("TESTING!!!");
}
}
Why can’t java find my method?
Because of the way Java was designed.
Java is "statically typed" that means objects types are checked during compilation.
In Java you can invoke a method only if that method belongs to that type.
Since this verification is made during compilation and the Object type does not have the "testing()" method, the compilation fails ( even though if at runtime the objects do have that method". This is primarily for safety.
The workaround as described by others will require you to create a new type, where you can tell the compiler
"Hey, the instances of this type will respond the the testing method"
If you want to pass a variety of objects and keep it very generic, one way is having those objects to implement and interface.
public interface Testable {
public void testing();
}
class A implements Testable { // here this class commits to respond to "testing" message
public void testing() {
}
}
class B implements Testable { // B "is" testable
public void testing() {
System.out.println("Testing from b");
}
}
class C implements Testable { // C is... etc.
public void testing() {
//....
}
}
Later somewhere else
public void doTest( Testable object ) {
object.testing();
}
doTest( new A() );
doTest( new B() );
doTest( new C() );
The "OTHER" way to do this, in java is invoking the methods reflectively, but I'm not sure if that's what you need, for the code is much more abstract when you do it that way, but that's how automated testing frameworks (and a lot of other frameworks such as Hibernate) do actually work.
I hope this help you to clarify the reason.
If you REALLY, REALLY want to keep the parameter as abstract as possible, you should consider reflection API. That way, you can pass whatever object you want and dynamically execute the method you want. You can take a look at some examples.
It's not the only way, but it might be a valid alternative depending on your problem.
Keep in mind that reflection is way slower than calling your methods directly. You might consider using an interface as well, such as the one on Amanda's post.

Categories

Resources