At work I came across the following design in a java project:
Consider interfaces Foo, Bar, and Baz as follows:
interface Bar { public int a(); }
interface Baz { public int b(); }
interface Foo extends Bar, Baz { public int c(); }
Now, consider class FooImpl:
public class FooImpl implements Foo {
private Bar bar;
private Baz baz;
public int a() {
return bar.a();
}
public int b() {
return baz.b();
}
public int c() {
return 0;
}
}
What are the use cases for this kind of class hierarchy? It seems to me that this introduces a lot of boilerplate and does not add much in terms of abstraction, other than breaking up what could be a large file into smaller files.
It allows things like this:
Foo foo = new FooImpl();
useBar(foo);
public void useBar(Bar bar) {
bar.a();
}
Whether this is useful depends on the real context. Your example code with classes and methods with meaningless names does not support a rational judgement.
The other thing to note is your FooImpl is actually implemented as some kind of wrapper for Bar and Baz instances. That's not (strictly speaking) an interface design issue.
I think it's a workaround for multiple inheritance (which is not allowed in Java). You're not showing implementations for Bar and Baz, but let's suppose they exist:
public class BarImpl implements Bar {
#Override
public int a() {
return 1;
}
}
public class BazImpl implements Baz {
#Override
public int b() {
return 2;
}
}
You neither have told us how Bar and Baz attributes are instantiated and set to FooImpl, because, if executed as stated in your question, you'll get a NullPointerException both in FooImpl.a() and FooImpl.b(). Again, let's imagine how this could be achieved:
public class FooImpl implements Foo {
private Bar bar; // better if final
private Baz baz; // better if final
// Constructor to properly initialize bar and baz
public FooImpl(Bar bar, Baz baz) {
this.bar = bar;
this.baz = baz;
}
#Override
public int a() {
return bar.a();
}
#Override
public int b() {
return baz.b();
}
#Override
public int c() {
return 0;
}
}
Wiring everything up:
Bar bar = new BarImpl();
Baz baz = new BazImpl();
Foo foo = new FooImpl(bar, baz);
int one = foo.bar(); // 1
int two = foo.baz(); // 2
In a way, FooImpl is "inheriting" from both BarImpl and BazImpl, though this is achieved by means of delegation.
To do this is really just redirecting fooimpl using its propertie's(bar and baz) "a" method and "b" method
Related
I've inherited some code, and I'm trying to refactor it in an attempt to clean it up.
This is a simplified case of how I received the code:
public class Foo
{
private void doSomething()
{
someOtherAction(Foo.this);
}
protected class FooChildClass
{
protected void anotherAction()
{
createDialogBox(Foo.this);
}
}
}
//totally not related to class Foo even though most code is duplicated
public class Bar
{
private void doSomething()
{
someOtherAction(Bar.this);
}
protected class BarChildClass
{
protected void anotherAction()
{
createDialogBox(Bar.this);
}
}
}
Now, here's the catch - after further examination of the code, Bar is almost a carbon-copy of Foo with some slight changes here and there.
I'd like to condense my code into something like this:
//superclass
public class Foo
{
protected void doSomething()
{
someOtherAction(Foo.this);
}
protected class ChildClass
{
protected void anotherAction()
{
createDialogBox(Foo.this);
}
}
}
//inherits from Foo and only overrides when necessary
public class Bar extends Foo
{
//rely on base implementation of doSomething
//override other functions only when necessary
}
Will my condensed code run successfully? I have a C# background, so I understand a good bit of Java syntax, but C# doesn't have anything similar to ClassName.this.
I'm figuring that ClassName.this is meant to resolve scoping issues by defining what 'this' is intended - and that with my modified code, Bar is indeed a Foo object too - but I figure I would ask to be sure!
Edited original question for clarification
Foo.this is equivalent to this. Therefore your condensed code is Okay with no requirement of being changed.
The following test code is to test your updated program:
Foo f = new Foo();
Foo.ChildClass fc = f.new ChildClass();
f.doSomething();
fc.anotherAction();
Bar b = new Bar();
Bar.ChildClass bc = b.new ChildClass();
b.doSomething();
bc.anotherAction();
The output is:
Foo#52e922
Foo#52e922
Bar#25154f
Bar#25154f
Referring to your most recent edit I composed the following example:
public class Foo {
public void printMe() {
System.out.println("I'm foo");
}
public class Child {
public void printMe() {
Foo.this.printMe();
}
}
}
public class Bar extends Foo {
#Override
public void printMe() {
System.out.println("I'm bar");
}
}
public class Main {
public static void main(String[] args) {
new Bar().new Child().printMe();
}
}
The result was:
I'm bar
Which concludes, that Foo.this.printMe() does not statically refer to the outer class Foo, but to the outer instance of the Child instance, which in this case is an instance of Bar.
For further reading:
The Classname.this syntax is used for inner classes.
You can use the following example to try a bit around and see its effects:
public class Foo {
private int value = 1;
public class Bar {
private int value = 2;
public void printValue() {
System.out.println(Foo.this.value);
}
}
}
Regarding derivation, there's no way to explicitly refer to a certain super type in java, like in C. However, you can refer to your super class using the super keyword.
With java 1.8 and default interface methods, the Classname.super syntax was introduced:
public interface Foo {
default int getValue() {
return 1;
}
}
public interface Bar {
default int getValue() {
return 2;
}
}
public class Impl implements Foo, Bar {
#Override
public int getValue() {
return Bar.super.getValue();
}
}
However, you can still only refer to direct super types. Everything other will be denied by the compiler.
Is it possible to tell Guice that it's not necessary to inject all constructor arguments? For example, I have a constructor Foo that takes two args of types Bar and Baz. All of them are optional in my system: they may
both present
both missing
only Bar present
only Baz present.
That said, it depends on other modules providing these bindings. I want to get something like this:
class Foo {
private final Bar bar;
private final Baz baz;
#Inject(optional = true)
public Foo(#Nullable Bar bar, #Nullable Baz baz) {
this.bar = bar;
this.baz = baz;
}
}
But I can't really use optional with constructors. Is there a way to do that?
I think the preferred Guice pattern for this is:
public class HolderPatter {
static class Bar {
#Inject Bar(BarDependency dependency) {}
}
static class Baz {
#Inject Baz(BazDependency dependency) {}
}
static class BarHolder {
#Inject(optional=true) Bar value = null;
}
static class BazHolder {
#Inject(optional=true) Baz value = null;
}
static class Foo {
private final Bar bar;
private final Baz baz;
#Inject
public Foo(BarHolder bar, BazHolder baz) {
this.bar = bar.value;
this.baz = baz.value;
}
}
}
Note that this will also allow you to specify sane default values...
The latest version of Guice recently added OptionalBinder which works better than the #Inject(optional=true) method and also adds several advanced features.
See also the thread where OptionalBinder was announced.
If I have the following class, Foo, where Bar is also a class:
public class Foo {
private Bar baz;
public Foo() {
}
}
Am I right in thinking that if I initialise baz where it is declared I will have an aggregate relationship between Foo and Bar and if I initialise baz in Foo's constructor I will have a composite relationship? Like this:
Aggregate (I think this is probably incorrect?):
public class Foo {
private Bar baz = new Bar();
public Foo() {
}
}
Composite:
public class Foo {
public Foo() {
baz = new Bar();
}
}
I'm a little new to Java, and seeing as everything is a class, I'm having difficulty visualising how (in particular) the aggregate relationship works unless I make baz static. If I create baz somewhere else and pass it in to the constructor of Foo, then won't baz just be a composite of some other class? Bit confuzzled.
Try reading more about the dependency injection. It's what you describe in your last sentence. Its a pattern that removes hard-coded dependencies as in both of your examples, but this job is delegated to a higher-level authority.
You would get something like:
public class Foo {
private Bar baz;
public Foo(Bar baz) {
this.baz= baz;
}
}
The actual instance of baz can be changed in both compile and runtime.
The actual composition means that class Bar has no meaning (or value) without the class Foo, and it cannot exist without the Foo, - Bar "is a part of" Foo. An example would be: an IMEI number is a part of the phone.
The aggregation tells that Foo only owns the Bar, - Bar "has" Foo. An example would be: a battery is a part of the phone. Other devices that are not phones could also have batteries.
These two concepts don't have much to do with the way you code it.
Composition
final class Car{
private final Engine engine;
Car(EngineSpecs specs) {
engine = new Engine(specs);
}
void move() {
engine.work();
}
}
Aggregation
final class Car {
private Engine engine;
void setEngine(Engine engine) {
this.engine = engine;
}
void move() {
if (engine != null)
engine.work();
}
}
This is a very odd question, so please bear with me.
I'd like to know if the Java specification guarantees that an overriding method in two subclasses is resolved via identical mechanisms in each. In other words, if I have
public class Foo {
public int frob() {
return 7;
}
}
public class Bar extends Foo {
#Override
public int frob() {
return 8;
}
}
public class Baz extends Foo {
#Override
public int frob() {
return 9;
}
}
and a method somewhere:
public static int quux(Bar b) {
return b.frob();
}
which I know only calls .frob() on b, how safe is it to call quux((Bar)new Baz())?
quux((Bar)new Baz()) will not even compile. (Cannot cast from Baz to Bar since Baz IS-NOT a Bar).
- Bar IS-A Foo, and Baz IS-A Foo.
- But neither Bar is a Baz nor Baz is a Bar, so this casting won't work.
This is what I'm trying to do (in Java 1.6):
public class Foo {
public Foo() {
Bar b = new Bar();
b.setSomeData();
b.doSomethingElse();
this(b);
}
public Foo(Bar b) {
// ...
}
}
Compiler says:
call to this must be first statement in constructor
Is there any workaround?
You could implement it like this:
public class Foo {
public Foo() {
this(makeBar());
}
public Foo(Bar b) {
// ...
}
private static Bar makeBar() {
Bar b = new Bar();
b.setSomeData();
b.doSomethingElse();
return b;
}
}
The makeBar method should be static, since the object corresponding to this is not available at the point you are calling the method.
By the way, this approach has the advantage that it does pass a fully initialized Bar object to the Foo(Bar). (#RonU notes that his approach does not. That of course means that his Foo(Bar) constructor cannot assume that its Foo argument is in its final state. This can be problematical.)
Finally, I agree that a static factory method is a good alternative to this approach.
You can implement the "default constructor" as a static factory method:
public class Foo {
public static Foo createFooWithDefaultBar() {
Bar b = new Bar();
b.setSomeData();
b.doSomethingElse();
return new Foo(b);
}
public Foo(Bar b) {
// ...
}
}
Like it says, a call to this() must be the first thing to happen in a constructor. Is there any reason this wouldn't work?
public class Foo {
public Foo() {
this(new Bar());
Bar b = getBar();
b.setSomeData();
b.doSomethingElse();
}
public Foo(Bar b) {
// ...
}
}