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.
Related
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;
}
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...
}
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.
public abstract class Test {
private static int value = 100;
}
And
public abstract class Test {
private int value = 100;
}
Since Test is abstract, it can't be instantiated, and therefore it doesn't make any difference whether value is static or not, right?
Is there any difference when a field is static or not when it belongs to an abstract class?
Yes, there is. Even thou your class is abstract, it can have non-abstract non-static methods working with non-static private fields. It is usefull sometimes.
Dummy exaple:
Consider following: you want to hold one integer and give everyone the ability to change it, but you dont want them to set negative values, or values bigger then 15, but the condition isn't known (in general) by everyone, so you want to ensure that when someone sets incorect value, it gets fixed automaticly.
Here is one possible solution:
abstract class MyInt {
private int myInt;
public int getMyInt() {
return myInt;
}
public void setMyInt(int i) {
myInt = checkMyInt(i);
}
protected abstract int checkMyInt(int i);
}
Now you can inplement any logic in checkMyInt() and hand over the instance declared as MyInt
pastebin exaplme
PS: this probably isnt the best solution and i would use interfaces here, but as an example it is enought i hope
Abstract classes can't be instantiated directly. But the whole point of abstract classes is to have subclasses that are instantiated:
public abstract class Test
protected int value;
}
public class TestImpl extends Test {
public TestImpl(int value) {
this.value = value;
}
}
In the above example, each instance of TestImpl (and thus of Test) has its own value. With a static field, the field is scoped to the Test class, and shared by all instances.
The difference between static and non-static fields is thus exactly the same as with any other non-abstract class.
An abstract class is a normal (base) class, just declared to be missing some things, like abstract methods.
So there is definite a difference.
I know it is not a good coding practice to declare a method as private in an abstract class. Even though we cannot create an instance of an abstract class, why is the private access modifier available within an abstract class, and what is the scope of it within an abstract class? In which scenario is the private access specifier used in an abstract class?
check out this code where Vehicle class is abstract and Car extends Vehicle.
package com.vehicle;
abstract class Vehicle {
// What is the scope of the private access modifier within an abstract class, even though method below cannot be accessed??
private void onLights(){
System.out.println("Switch on Lights");
}
public void startEngine(){
System.out.println("Start Engine");
}
}
Within is the same package creating a Car class
package com.vehicle;
/*
* Car class extends the abstract class Vehicle
*/
public class Car extends Vehicle {
public static void main(String args[]){
Car c = new Car();
c.startEngine();
// Only startEngine() can be accessed
}
}
Since an abstract class can contain functionality (as opposed to an interface) it can have private variables or methods.
In your example you might do something like
public void startEngine(){
injectFuel();
igniteSpark();
// etc. my understanding of engines is limited at best
System.out.println("Start Engine");
}
private void injectFuel() {}
private void igniteSpark() {}
That way you can spread some of the work to other methods (so you don't have a 1000 line startEngine method), but you don't want the children to be able to call injectFuel separately since it doesn't make sense outside the context of startEngine (you want to make sure it's only used there).
Or even more you might have a private method that gets called in several other public methods, with different parameters. This way you avoid writing the same code twice or more in each of the public methods, and grouping the common code in a private method makes sure the children don't access it (like they couldn't just call part of the public method before). Something like this:
public void startEngine() {
dishargeBattery(50);
System.out.println("Start Engine");
}
public void startRadio() {
dischargeBattery(20);
}
private void dischargeBattery(int value) {
battery.energy -= value; //battery should probably be a private field.
}
This way your methods can have access to the battery, but the children shouldn't mess with it, and you don't write the same line (battery.energy -= value) in both of them. Take note though, that these are very simple examples, but if dischargeBattery was a 500 line method, writing it in both the other methods would be a hassle.
It's the same as in a non-abstract class, there's no difference.
Which means that if nothing in your abstract class calls the private method, then you can just as well remove it, as it won't be called (baring some evil reflection work).
Usually, private methods are only used as internal utility methods that have a very specific task that the other methods in the class use to do their work.
I know it is not a good coding
practice to declare a method as
private in an abstract class.
I don't. Where did you get that idea?
what is the scope of it within an abstract class?
The abstract class.
The method can be accessed only from within the abstract class. For example, you could have an abstract class with a public final method that makes use of a private helper method.
package arrayafter;
public abstract class Abstract_Demo {
abstract void display();
private void display1() {
System.out.println("Private Method");
}
final void display2() {
System.out.println("final Method");
display1();
}
public static void display3() {
System.out.println("Static methods");
}
}
package arrayafter;
import java.util.Scanner;
public class Practice extends Abstract_Demo{
public static void main(String[] args) {
Practice pr=new Practice();
pr.display();
pr.display2();
Abstract_Demo.display3();
}
#Override
void display() {
// TODO Auto-generated method stub
System.out.println("Abstract method");
}
}