How can one create an abstract, immutable class? - java

Here's the short version. First and foremost: I want my class to be immutable. I know that a class can't be both abstract and final. What I'm asking is: is there a way to only allow inner classes to extend and implement the outer, abstract class? This may not be the best method to achieve my immutable goals, so if somebody has a better design, I would love to hear it.
I am writing a class for vector operations -- as in physics and engineering, not the programming sense. (I'm also aware that JScience has a package for this kind of stuff. I want to write my own, and keep it simple.)
I like the pattern used in Java's geometry package, wherein, say, a Line2D can be created using one of two precision levels: float or double.
public abstract class Line2D {
public static class Float extends Line2D { /* Implementation */ }
public static class Double extends Line2D { /* Implementation */ }
}
This is a feature I would really like to incorporate and expand upon in my class, so I created the following:
public abstract class Vector2D {
public final static class Integer extends Vector2D {
// Component length projected along x/y axis, respectively
final private int i, j;
public Integer( int i, int j ) {
this.i = i;
this.j = j;
}
public Object doStuff() { /* vector operations */ }
}
public final static class Float extends Vector2D {
// Identical to Vector2D.Integer, except with floats
}
public final static class Double extends Vector2D { /* Same Idea */ }
// Outer class methods and whatnot
}
Obviously, Vector2D.Integer, Vector2D.Float, and Vector2D.Double are all final. Is there any way to make Vector2D final to everything except these inner classes?

Is there a way to only allow inner classes to extend and implement the outer, abstract class?
Yes, make the constructor of the outer class private.
Example:
abstract class MyAbstractClass {
int i; // some property
private MyAbstractClass(int i) {
this.i = i;
}
public static class InnerConcrete extends MyAbstractClass {
int j; // some other property
public InnerConcrete(int i, int j) {
super(i);
this.j = j;
}
}
}
I don't think I've ever come across this approach. A factory pattern may be more flexible and allows you split the otherwise potentially large class into several files. Package access level of the abstract class may perhaps also be sufficient.

Is there a way to only allow inner classes to extend and implement the outer, abstract class?
I would opt for another alternative: make your abstract classes non-public and only make public the final implementation classes. This is the case of AbstractStringBuilder, which belongs to java.lang package, is abstract and non-public, and it's implemented by StringBuilder and StringBuffer classes, which are public final.
Here's the relevant source code of these classes:
abstract class AbstractStringBuilder implements Appendable, CharSequence {
//implementation details...
}
public final class StringBuilder
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence {
//implementation details...
}
public final class StringBuffer
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence {
//implementation details...
}

Related

Extending a generic class into a static inner class

I am having issues extending an inner class with a generic abstract class.
I get an Non-static field cannot be referenced from a static context which is odd because the class itself is static, not necessarily the field value.
This is basically what I have:
// AbstractFoo.java
public abstract class AbstractFoo extends FrameLayout {
// Some logic
}
// AbstractBar.java
public abstract class AbstractBar<T> {
int someNumber;
// Some logic
}
// Foo.java
public class Foo extends AbstractFoo {
// Some logic
// Foo.InnerFoo.java
public static class InnerFoo extends AbstractBar<InnerFoo> {
public InnerFoo() {
super.someNumber = 5; // Compiler error HERE
}
}
}
For some reason I cannot access someNumber from InnerFoo. From my understanding this shouldn't cause any issues. The classes I'm extending btw is from an external library.
This is also all done with Android where minimum SDK is 24.
Thanks for the help!
The fields defined in your classes do not have an explicit access modifier which would use the default access modifier and limit the visibility to classes within the same package.
You should make the fields in AbstractBar as protected -
public abstract class AbstractBar<T> {
protected int someNumber;
}

JAVA Inheriting static field from base class in the way that it will differ for every subclass

I have a base class
public class base
{
//some stuff
}
and several subclasses
public class sub1 extends base
{
static int variable;
}
public class sub2 extends base
{
static int variable;
}
etc
The static int variable exists in every subclass because I store in it information that is characteristic for every subclass. But it would be better if there was a way to move static int variable to base class in the way that it still will be different for every subclass.
In the way that it is now I am repeating myself, when adding some another subclass, it's a bad practice.
So anyone has some idea how to acomplish this? Maybe there's a design pattern that fits to this situation?
You cannot move all the different static variables from derived classes into the base class, because static variables are one-per-class; you want your variables to be one-per-subclass, which is not allowed.
You could work around this issue by defining a registry of subclasses in your base class, and store the int for each subclass there. However, this would add a lot more complexity, and it is not clear how you would differentiate between subclasses in the superclass.
Your current solution appears optimal.
Don't use a static field for this - that's not the way to go, because static fields of a subclass do not "override" those of a super class.
Instead, because the values are constant for a given class, use a final instance field:
public class Base {
protected final int variable;
public Base() {
this(5);
}
protected Base(int v) {
variable = v;
}
}
public class Sub1 extends Base {
private static int v = 7;
public Sub1() {
super(v);
}
}
Now the variable is fixed and accessible to all instances.
You can certainly move variable into the base class, but it cannot be static. Alternatively, you can make static getters which you override in each subclass. Here is an example of both:
public class base {
protected int variable;
protected static int getVariable() {
return -1;
}
}
public class Sub1 extends base {
public Base() {
variable = 0;
}
protected static int getVariable() {
return 0;
}
}
public class Sub2 extends base {
public Sub2() {
variable = 1;
}
protected static int getVariable() {
return 1;
}
}
As a design principle, it is somewhat rare (in my opinion) that you genuinely want static methods. Usually you will have some instance of the class around that you are working with. If you want a whole bunch of objects to share some common behavior which you configure at runtime, you might want to check out the flyweight pattern.

protected integers in static classes

Let's say I have a
public abstract class Super{
protected static int BASE = 1;
public int foo(){
//do some computation with BASE, e.g:
return BASE + 1;
}
}
and a couple static classes inheriting from it:
public static abstract class Sub extends Super{
//this class should keep BASE at 1
}
static class SubSub1 extends Sub{
//this class should change BASE to 0
static{
SubSub1.BASE = 0;
}
}
static class SubSub2 extends Sub{
//this class should in effect have a BASE of 1
}
And yes, this fails.
The problem obviously is that since SubSub1 is a static class, if it is to change BASE, Super.BASE must be static.
But if Super.BASE is static, then SubSub1.Base IS Super.BASE.
How do I best achieve what I'm trying to do? (No, I can't make the classes non-static, and assume there are a lot of subclasses.)
I'd appreciate the help.
There are no static classes in Java. All Java classes are implicitly static, except nested classes. Interfaces, Annotations and Enums are always static.
The actual issue is a different one: there is no static inheritance in Java. A subclass does not get a copy of the static superclass field, it gets the same field. Whether you reference it as SubSub.BASE or as Super.BASE doesn't matter, it is Super.BASE
Actually, the "abstract protected int getBase()" wasn't so bad an idea - I just didn't like that "abstract" part since I would have had to implement that in all non-abstract subclasses.
This, on the other hand, seems to be working and allows me to change BASE only where I need it to change:
public abstract class Super{
protected int BASE = 1;
protected void setBase(){}
public int foo(){
setBase();
return BASE + 1;
}
}
and then:
public static abstract class Sub extends Super{
//this class should keep BASE at 1
}
static class SubSub1 extends Sub{
//this class should change BASE to 0
#Override
protected void setBase(){
BASE = 0;
}
}
static class SubSub2 extends Sub{
//this class should still have a BASE of 1
}
Thanks a lot, guys.

How do I convert an abstract class into an interface?

I have a java program which uses arraylists - these arraylists store 'variables' where 'variables' is an abstract class.
Now, to save memory, I want to use a java library called HugeCollections-VanillaJava- however this library requires an interface to be defined.
How do I convert the abstract class into an interface? What rules/restrictions do I have to follow, to correctly perform the conversion?
Finally, is it possible for me to use my abstract class with minimal code changes, so that the library that requires an interface, also works correctly? Ideally I would like not to change the abstract class at all...Is this possible?
how do I convert an abstract class into an interface?
Make a copy of the abstract class source file.
Change "class" to "interface" in the initial declaration.
Change the name (optionally, depends on what you're doing).
Remove the bodies of any methods that are implemented by the class.
Remove the word "abstract" from the other ones.
Remove all private and protected members.
Remove all constructors.
Remove the keyword "public" from the public members.
If you had any code you removed (implemented methods, private or protected stuff), have your original abstract class implement your interface and leave that stuff there.
(Incomplete) Example:
Foo as an abstract class:
public abstact class Foo
{
private int bar;
public static final int SOME_CONSTANT = 42;
public Foo(b) {
this.bar = b;
}
public abstract void doSomething(String s);
protected int doSomethingElse() {
return this.bar * 2;
}
}
Foo as an interface:
public interface Foo
{
int SOME_CONSTANT = 42;
void doSomething(String s);
}
In my case, as I did have some stuff the old Foo did, I'd probably have AbstractFoo or something:
public abstact class AbstractFoo implements Foo
{
private int bar;
public Foo(b) {
this.bar = b;
}
public abstract void doSomething(String s);
protected int doSomethingElse() {
return this.bar * 2;
}
}
...so that an implementation could use it as a starting point if desired (although with that private bar in there, it doesn't make a lot of sense).
Pattern Adapter might help you.
Imagine, you're have to use SomeClass as TargetInterface
public abstract class SomeClass {
// some code here
public abstract void someMethod();
}
public interface TargetInterface {
public void someMethodBlaBla();
}
And they have different signatures of methods - someMethod() and someMethodBlaBla().
So you're might create such adapter class:
public class Adapter implements TargetInterface {
private SomeClass adaptee;
public Adapter( SomeClass adaptee ) {
this.adaptee = adaptee;
}
public void someMethodBlaBla() {
this.adaptee.someMethod();
}
//delegate all calls to adaptee
}
and somewhere in code you might use both - adapter and instance of abstract class, without interference on current code:
SomeClass abstractClassInstance = ... //get instance of your abstract class
TargetInterface targetInterfaceInstance = new Adapter( abstractClassInstance );
If abstract class does not define any concrete methods, you can even use regular expression for that. From:
public abstract class Abstract {
public abstract void method();
//...
}
to:
public interface Interface {
void method();
//...
}
public abstract modifiers are implicit for interfaces. If the abstract class does define some methods (not all methods are abstract) or have some fields this can't be done (at least easily).

Extending Java Enums

I have a question regarding the best design pattern for code reuse when dealing with Java enums. Basically, what I'm trying to achieve is being able to define several enums that model static business collections (sets of constants), but I'd also like to share behavior between them, with minimal coding.
This is trivial to achieve with class inheritance from abstract classes but, since Java enums cannot be extended (they can only implement interfaces), this type of work is tedious and involves a lot of error prone copy/paste work (copying the code from enum to enum). Examples of "business logic" that should be shared among all enums includes converting from/to Strings, instance and logical comparison, etc.
My best shot right now is using helper classes in conjunction with business interfaces, but this only goes so far in reducing code complexity (as all enums still have to declare and invoke the helper classes). See example (just to clarify):
public enum MyEnum {
A, B, C;
// Just about any method fits the description - equals() is a mere example
public boolean equals(MyEnum that) {
ObjectUtils.equals(this, that);
}
}
How do StackOverflowers deal with this "language feature"?
You can move the reusable logic to dedicated (non-enum) classes and then have the enums delegate to those classes. Here's an example:
[Side note: the inheritance of PlusTwo extends PlusOne is not recommended (b/c PlusTwo is not PlusOne). It here just to illustrate the point of being able to extend an existing logic.]
public interface Logic {
public int calc(int n);
}
public static class PlusOne implements Logic {
public int calc(int n) { return n + 1; }
}
public static class PlusTwo extends PlusOne {
#Override
public int calc(int n) { return super.calc(n) + 1; }
}
public static enum X {
X1, X2;
public Logic logic;
public int doSomething() {
return logic.calc(10);
}
}
public static enum Y {
Y1, Y2;
public Logic logic;
public String doSomethingElse() {
return "Your result is '" + logic.calc(10) + "'";
}
}
public static void main(String[] args) {
// One time setup of your logic:
X.X1.logic = new PlusOne();
X.X2.logic = new PlusTwo();
Y.Y1.logic = new PlusOne();
Y.Y2.logic = new PlusTwo();
System.out.println(X.X1.doSomething());
System.out.println(X.X2.doSomething());
System.out.println(Y.Y1.doSomethingElse());
System.out.println(Y.Y2.doSomethingElse());
}
I would do the same, or combine the Enums into a super-enum.
With Java 8 this will be easier. You will be able to define a default implementation for interface methods and have the enum extend the interface.
I rarely find enums useful, except for representing finite states in which case they do not need behavior.
I would suggest refactoring enums that need behavior into classes with a Factory.
This might look a bit ugly, but generally can offer you the required functionality.
You can have interface
public interface MyEnumInterface<T extends Enum<T>> {
String getBusinessName();
T getEnum();
}
Implementation
public enum OneOfMyEnums implements MyEnumInterface<OneOfMyEnums>{
X, Y, Z;
#Override
public String getBusinessName() {
return "[OneOfMyEnums]" + name();
}
#Override
public OneOfMyEnums getEnum() {
return this;
}
}
And utility class instead of your parent class
public class MyEnumUtils {
public static <T extends Enum<T>> String doSomething(MyEnumInterface<T> e){
e.getBusinessName(); // can use MyEnumInterface methods
e.getEnum().name(); // can use Enum methods as well
return null;
}
}

Categories

Resources