Static Factories Methods - java

One advantage of static factories method states that:
Unlike constructors they can return an object of any subtype of their return type which gives you great flexibility in choosing the class of returned object.
What does this mean exactly?
Can someone explain this with code?

public class Foo {
public Foo() {
// If this is called by someone saying "new Foo()", I must be a Foo.
}
}
public class Bar extends Foo {
public Bar() {
// If this is called by someone saying "new Bar()", I must be a Bar.
}
}
public class FooFactory {
public static Foo buildAFoo() {
// This method can return either a Foo, a Bar,
// or anything else that extends Foo.
}
}

Let me break your question in two parts
(1) Unlike constructors they can return an object of any subtype of their return type (2) which gives you great flexibility in choosing the class of returned object.Let say You have two classes Extended from Player which are PlayerWithBall and PlayerWithoutBall
public class Player{
public Player(boolean withOrWithout){
//...
}
}
//...
// What exactly does this mean?
Player player = new Player(true);
// You should look the documentation to be sure.
// Even if you remember that the boolean has something to do with a Ball
// you might not remember whether it specified withBall or withoutBall.
to
public class PlayerFactory{
public static Player createWithBall(){
//...
}
public static Player createWithoutBall(){
//...
}
}
// ...
//Now its on your desire , what you want :)
Foo foo = Foo.createWithBall(); //or createWithoutBall();
Here you get the both answers Flexability and unlike constructor behaviour
Now You can see through these factory methods its upto you that WHICH TYPE OF PLAYER YOU NEED

Related

java virtual method that does not return void

I want a method in a derived class to override a virtual method in a CONCRETE base class AND return something (i.e. not void) like this:
public class HelloWorldApp
{
public static void main(String args[])
{
Bar bar = new Bar();
bar.go();
}
}
public class Foo
{
public void go()
{
System.out.print(this.test().toString());
}
protected Integer test()
{
return 1;
}
}
public class Bar extends Foo
{
#Override
protected Integer test()
{
return 2;
}
}
Is there any way of doing this without the redundant 'return 1;' in Foo.test() which will never get run. It works fine obviously but it just seems like I'm doing something badly wrong.
This answer was created before the question was updated to state that the base class must be concrete.
If you expect Foo's test method never to be run, then enforce it by making the Foo class abstract, with test being abstract.
public abstract class Foo {
public void go() {
System.out.print(this.test().toString());
}
abstract protected Integer test();
}
If you cannot make Foo.test() abstract for some reason you didn't show in your example (for example because Foo extends a concrete class) and you are sure it will never be called, throwing a runtime exception may be preferable if there is no reasonable default value:
protected Integer test()
{
throw new UnsupportedOperationException("Calling test on Foo is not supported");
}
There are examples for this in the Java core APIs, see for example UnsupportedOperationException - this one has a slightly different meaning though, it is used for optional methods that some implementations of certain collection-types implement and some don't.

How to allow a user to choose what class to initialise

I have an abstract class Foo, which contains a function a(Object o).
Depending on what implementation of Foo you use, a(Object o) is implemented slightly differently.
I want the user of the program to be able to determine what implementation of Foo is used (eg., aFoo,bFoo, cFoo, etc), but I want to cut down on my use of conditional logic so that I can add to my program more safely in the future.
I currently have an Enum eBar that holds the names of all the implementations of Foo, which the user can choose from, but I am unable to determine how to use that to initialise the class.
Store the instance of Foo to use, or add a method creating the Foo to use, in each enum instance:
public enum FooType {
A {
#Override
public Foo createFoo() {
return new AFoo();
}
},
B {
#Override
public Foo createFoo() {
return new BFoo();
}
}
public abstract Foo createFoo();
}
Then, once the user has chosen the type, all you need to do is
selectedFooType.createFoo().a(object);
[EDIT] You can do that using an Enum like below
public enum FooType {
FOO_A(aFoo::new),
FOO_B(bFoo::new),
FOO_C(cFoo::new);
//add as much as you want here
private final Supplier<Foo> fooSupp; //the aim of using a supplier is to create a new instance each time you call the create method as mentioned in the comment.
FooType(final Supplier<Foo> fooSupp) {
this.fooSupp = fooSupp;
}
public final Foo create(){
return this.fooSupp.get();
}
}
Then you can use it like this
final Foo myFoo = FooType.FOO_A.create();
myFoo.o(Object);

When two interfaces have conflicting return types, why does one method become default?

In Java 8, if I have two interfaces with different (but compatible) return types, reflection tells me that one of the two methods is a default method, even though I haven't actually declared the method as default or provided a method body.
For instance, take the following code snippet:
package com.company;
import java.lang.reflect.Method;
interface BarInterface {}
class Bar implements BarInterface {}
interface FooInterface {
public BarInterface getBar();
}
interface FooInterface2 extends FooInterface {
public Bar getBar();
}
class Foo implements FooInterface2 {
public Bar getBar(){
throw new UnsupportedOperationException();
}
}
public class Main {
public static void main(String[] args) {
for(Method m : FooInterface2.class.getMethods()){
System.out.println(m);
}
}
}
Java 1.8 produces the following output:
public abstract com.company.Bar com.company.FooInterface2.getBar()
public default com.company.BarInterface com.company.FooInterface2.getBar()
This seems odd, not only because both methods are present, but also because one of the methods has suddenly and inexplicably become a default method.
Running the same code in Java 7 yields something a little less unexpected, albeit still confusing, given that both methods have the same signature:
public abstract com.company.Bar com.company.FooInterface2.getBar()
public abstract com.company.BarInterface com.company.FooInterface.getBar()
Java definitely doesn't support multiple return types, so this result is still pretty strange.
The obvious next thought is: "Okay, so maybe this is a special behavior that only applies to interfaces, because these methods have no implementation."
Wrong.
class Foo2 implements FooInterface2 {
public Bar getBar(){
throw new UnsupportedOperationException();
}
}
public class Main {
public static void main(String[] args) {
for(Method m : Foo2.class.getMethods()){
System.out.println(m);
}
}
}
yields
public com.company.Bar com.company.Foo2.getBar()
public com.company.BarInterface com.company.Foo2.getBar()
What's going on here? Why is Java enumerating these as separate methods, and how has one of the interface methods managed to become a default method with no implementation?
It's not a default method you provide but a bridging method. In the parent interface you have defined.
public BarInterface getBar();
and you must have a method which can be called which implements this.
e.g.
FooInterface fi = new Foo();
BarInterface bi = fi.getBar(); // calls BarInterface getBar()
However, you also need to be able to call it's co-variant return type.
FooInterface2 fi = new Foo();
Bar bar = fi.getBar(); // calls Bar getBar()
These are the same method, only difference is that one calls the other and cast the return value. It's the method which appears to have a default implementation as it is on the interface which does this.
Note: if you have multiple levels of interfaces/class and each has a different return type, the number of methods accumulates.
The reason it does this is that the JVM allows having multiple methods with different return type because the return type is part of the signature. I'e the caller has to state which return type it is expecting and the JVM doesn't actually understand co-variant return types.

Java: method only callable by superclass

I would like to prevent a class from calling its own method. The method shall only be callable by its super class.
Right now, I cannot think of any way to achieve this (cleanly). But maybe someone knows a solution?
In code:
public abstract class A {
protected abstract void foo();
private void barA() {
//do smth
foo();
}
}
public class B extends A {
#Override
protected void foo() {
//do smth
}
private void barB() {
//must not be able to call foo() here
}
}
Edit: the explanation why I would like to do this:
A is lets say a vehicle. B can be a car or an airplane. The method foo() would be startEngines(). -> I want to make sure that the engines can only be started by calling the method barA().... does that make any sense?
There is a way to do it, but you need to use Google Error Prone. This is an extension of the Java compiler that aims to provide more and more helpful warnings and errors (similar to FindBugs and PMD, but with less false alarms). I can only recommend it, it has already helped us to find some bugs.
Specifically, it contains an annotation #ForOverride and an according compile-time check. This annotation is meant to be used for protected methods that the sub-class and any other class should not call, but only the defining class.
So using
public abstract class A {
#ForOverride
protected abstract void foo();
private void barA() {
//do smth
foo();
}
}
would exactly achieve what you want.
You can integrate Error Prone into most build systems like Maven and Ant. Of course, it won't help if somebody compiles your source without Error Prone (for example in Eclipse), but using it in a continous-integration system would still allow you to find such issues. The source code still stays compatible with regular Java compilers (provided you have error_prone_annotations.jar on the class path), other compilers will simply not do the additional checks.
this answer has a good hint.
add below method in your class (class B):
public static String getMethodName(final int depth)
{
final StackTraceElement[] ste = Thread.currentThread().getStackTrace();
return ste[ste.length - 1 - depth].getMethodName();
}
and change the foo method in class B to this:
#Override
protected void foo() {
//....
if (getMethodName(0)=="barB"){
// tell you are not able to call barB
}
}
Considering your vehicle and engine scenario, I think you need to reconsider your design a bit.
Your vehicle could be a car, aeroplane, etc but car, aeroplane, ... each have separate engines and therefore different startEngine method. So declare your class vehicle as abstract like you did and class startEngine as abstract method . Next , subclass Vehicle and implement startEngine in them , now you can invoke startEngine on the subclass instances
abstract class Vehicle{
abstract void startEngine();
}
public class Car extends Vehicle{
public void startEngine(){
//implementation
}
public static void main(String[] arg){
Vehicle v=new Car();
v.startEngine();
}
}
Add Anonymouse inner class to barA method via Interface, so you will need to implement a method for foo() (functional interface). It won't be part of Class B.
you could put an interface as a member in the super class given to it via the constructor. the child class implements the method but can't call it except by making it static.
interface Foo {
void stopEngines();
void startEngines();
}
abstract class Base {
final private Foo foo;
public Base(final Foo foo) {
this.foo = foo;
}
private void barA() {
// do smth
foo.startEngines();
}
}
class Child extends Base {
public Child() {
super(new Foo() {
boolean engineRunning;
#Override
public void stopEngines() {
this.engineRunning = false;
}
#Override
public void startEngines() {
this.engineRunning = true;
}
});
}
private void barB() {
// can't call startEngines() or stopEngines() here
}
}
class Child2 extends Base {
public Child2() {
super(new Foo() {
#Override
public void stopEngines() {
stopEngines();
}
#Override
public void startEngines() {
startEngines();
}
});
}
static void stopEngines() {
// influence some static state?
}
static void startEngines() {
// influence some static state?
}
private void barB() {
// can call stopEngines() and startEngines(), but at least they have to be static
}
}
Of course, this is not really what you asked for, but about as much as you can do about it in Java, I guess.
Seeing the startEngines explanation, this solution might even suffice.
I guess you wouldn't care about the class calling its static methods, since they can only influence a static state, which is used seldom. The methods within the anonymous interface implementation can mutually call each other, but I guess that would be OK, since you only seem to be trying to prevent others to start the engines in some different way.
I guess this is similar to the problem AWT/Swing has with overriding the paint(Graphics g) method on a component (or onCreate(..) in Android Activities). Here you are overriding the paint method but you should never call it.
I think the best thing you can do is add documentation to the method to clarify that it should never be explicitly called by the subclasses OR re-evaluate your design.

Java Inheritance Question

I Have something similar to this setup:
public class Base {
public String getApple() {return "base apple"};
}
public class Extended extends Base{
public String getApple() {return "extended apple"};
}
Somewhere else in the code I have this:
{
Base b = info.getForm();
if (b instanceof Extended){
b = (Extended) b;
}
System.out.println(b.getApple()); // returns "base apple" even when if clause is true why??
}
How do I accomplish that?
First:
if (b instanceof Extended){
b = (Extended) b;
}
does absolutely nothing. You are basically saying b = b, which says nothing. You are not even changing the reference.
Second, getApple() will always be dynamically bound, and the "extended apple" should always be called - given that the subclass is truly extending the base class, and the method is truly overridden.
Basically what you need to do, in order to accomplish correct getApple() behavior:
remove the if clause. it does nothing.
make sure your class is indeed extending the base class
make sure the getApple() method is overriding the base class method. (use the #override annotation if you are not sure)
As written, your code will not compile, which makes me think that your problem is elsewhere. Your return statements don't have semicolons at the end of them. Rather, they appear after the }. It's possible you had some other problem (maybe your subclass misspelled getApple()), but you're still using your old class files because your new stuff isn't compiling.
This code works:
class Base {
public String getApple() { return "base apple"; }
}
class Extended extends Base {
public String getApple() { return "extended apple"; }
}
public class Test {
public static void main(String[] args) {
Base b = new Extended();
System.out.println(b.getApple());
}
}
Console:
#javac Test.java
#java Test
extended apple
First of all, that if block should never be necessary. It's basically a no-op.
Second, this isn't your real code, because it doesn't even compile. You're missing semicolons after the return statements.
I suspect that your problem is that your real code has a typo that's making the signatures of the two getApple methods different. This means that Extended has two methods: the one inherited from Base and the one with a different signature in itself. Since you're calling with the signature of the Base.getApple method, you're always getting that behavior. This is only a guess though, as your posted code does not exhibit the problem you describe.
Yuval is right that your cast in the if block has no effect. You might try combining your last statement with the if:
if (b instanceof Extended)
{
// Prints "extended apple" if reached.
System.out.println(((Extended)b).getApple());
}
Add #Override to the method in your subclass and recompile. This will help you find out if you're not actually overriding the method you think you are.
i.e.
public class Base {
public String getApple() {return "base apple";}
}
public class Extended extends Base{
#Override
public String getApple() {return "extended apple";}
}
The only way to get that behavior is to return super.getApple() in your extended class, which is effectively the same as not overriding it in the first place. The only way this could help is if you pass in an argument to decide which to return. Not saying thats good design...
Forgot to mention that, as Yuval said, the cast does nothing to the object.
You should investigate what is constructing your instance that is returned from info.getForm(). You may want to make the Base abstract to prevent it from being instantiated and you'll quickly see where construction is happening.
Are you sure your code example provided in your question EXACTLY matches the code your are using? The reason I ask is that the behavior you are describing happens when you access a public FIELD instead of a public METHOD with an object pointer.
For example:
public class BaseClass {
public String baseField;
public BaseClass() {
baseField = "base";
}
public String getBaseField() {
return baseField;
}
}
public class SubClass extends BaseClass {
public String baseField;
public SubClass () {
baseField = "sub";
}
public String getBaseField() {
return baseField;
}
}
public class MainClass {
public static void main(String[] args) {
BaseClass baseObject = new BaseClass();
SubClass subObject = new SubClass();
System.out.println(baseObject.getBaseField());
System.out.println(subObject.getBaseField());
System.out.println(baseObject.baseField);
System.out.println(subObject.baseField);
System.out.println(((BaseClass)subObect).getBaseField());
System.out.println(((BaseClass)subObect).baseField);
}
}
Will print out:
base
sub
base
sub
sub
base
When you call a method, the JVM will start at the bottom of the inheritance hierarchy and call the appropriate method. When you reference a field instead, it uses the class of the pointer instead of walking up the class hierarchy to resolve the value. The behavior of the field reference matches what you're seeing, which is why I ask for clarification/verification.

Categories

Resources