views:

657

answers:

10

I am coming from c# where this was easy, and possible.

I have this code:

public abstract class clsAbstractTable {

    public abstract String TAG;
    public abstract void init();

}

but Eclipse tells me I use illegal modifier.

I have this class:

public class clsContactGroups extends clsAbstractTable {


}

I want the variable and method defined in such way, that Eclipse to prompt me, I have unimplemented abstract variables and methods.

How do I need to define my abstract class so I should be prompted to implement the abstracts?

EDIT 1

I will create different classes for different db tables. Each class should have it's own TABLENAME variable, no exception. I have to make sure this variable is static each time when I create a new class that extends the abstract class.

Then in the abstract class I will have a method eg: init();

If in this init() method I call TABLENAME, it should take the value from the sub-class.

something like this should also work out

String tablename=(clsAbstract)objItem.TABLENAME;
// where objItem can be any class that extended clsAbstract;

EDIT 2

I want a constant(static) defined in each class having it's name defined in abstract.

  • I define variable TABLENAME in abstract, but no value given.
  • I create a clsContactGroups, I should be prompted to implement TABLENAME, this is where gets some data. eg: TABLENAME="contactgroups";
  • I create a second class clsContacts, I should be prompted to implement TABLENAME, this is where gets some data. eg: TABLENAME="contacts";
    etc...
+1  A: 

As there is no implementation of a variable it can't be abstract ;)

Thomas Wanner
+1  A: 

No, Java doesn't support abstract variables. It doesn't really make a lot of sense, either.

What specific change to the "implementation" of a variable to you expect a sub class to do?

When I have a abstract String variable in the base class, what should the sub class do to make it non-abstract?

Joachim Sauer
I want to make sure that the sub class defines that variable.
Pentium10
@Pentium10: you already said that, but why? What good would it do? Why not define it in the base class?
Joachim Sauer
I want to give value in the sub-class.
Pentium10
+4  A: 

No such thing as abstract variables in Java (or C++).

If the parent class has a variable, and a child class extends the parent, then the child doesn't need to implement the variable. It just needs access to the parent's instance. Either get/set or protected access will do.

"...so I should be prompted to implement the abstracts"? If you extend an abstract class and fail to implement an abstract method the compiler will tell you to either implement it or mark the subclass as abstract. That's all the prompting you'll get.

duffymo
I want to make sure that the sub class defines that variable. How can I be sure?
Pentium10
@Pentium10: what advantage would that have over simply defining the variable in the base class in the first place?
Joachim Sauer
I will create different classes for different db tables. Each class should have it's own TABLENAME variable, no exception. I have to make sure this variables is static each time when I create a new class that extends the abstract class.
Pentium10
See my edit to the question.
Pentium10
I doubt that you need one class per table. I belive one class with multiple instances created in memory will suffice.
duffymo
+10  A: 

Define a constructor in the abstract class which sets the field so that the concrete implementations are per the specification required to call/override the constructor.

E.g.

public abstract class AbstractTable {
    protected String name;

    public AbstractTable(String name) {
        this.name = name;
    }
}

When you extend AbstractTable, the class won't compile until you add a constructor which calls super("somename").

public class ConcreteTable extends AbstractTable {
    private static final String NAME = "concreteTable";

    public ConcreteTable() {
        super(NAME);
    }
}

This way the implementors are required to set name. This way you can also do (null)checks in the constructor of the abstract class to make it more robust. E.g:

public AbstractTable(String name) {
    if (name == null) throw new NullPointerException("Name may not be null");
    this.name = name;
}
BalusC
Beat me to it :)
seanhodges
I need this to be done with Static variables. As the variable will be static to the implemented class, like a tablename of the class. I do not want to pass the tablename to the constructor each time.
Pentium10
Static variables are shared among all instances of the class. If you set it, then it will be changed/reflected in **all instances** of the class, *regardless* of the implementation. Do you *really* want this? If so, then I really don't see any benefit of making them abstract ... Exactly due to the previous reason (affecting ALL instances). It's also technically impossible because it violates the OO ideology. You either need to learn Java/OO once again or to rethink your approach/design.
BalusC
See my edit to the question. I want a constant(tablename) defined in each class, having it's named defined in abstract.
Pentium10
Then my answer still applies. You don't need to make it static. It makes no sense.
BalusC
Sorry, but I don't understand. Since it's a per class data, eg. tablename, and not per instance. I see it needs to be static, as it won't change.
Pentium10
It can only be static in the concrete implementation, not in the abstract class, while you actually want to define it in the abstract class. If you make it static in the abstract class, it will affect all concrete implementations. Just call `super("sometablename")` and you're fine.
BalusC
"It can only be static in the concrete implementation" that is true. But how do I define in the abstract so I should be forced to make it static in the implementation?
Pentium10
You don't want it to be static. You'll have one instance per table, and the table name will be an instance variable. You'll initialize it in the constructor. You won't have one class per table; it's one instance per table.
duffymo
I would disagree with this implementation since it requires that the constructor always pass the value, even if that is a constant and even if for some instances it is not used. I think this is better implemented as a property (in Java a `getXXX()` method) which returns a static from the implementing sub-class. See my answer for an example. (Another problem - this way requires a reference to the tag/tablename in every instance of the sub-class, if you have 1000 sub-class instances then there are 1000 object references to the same static string.)
Kevin Brock
@Pentium10: I have edited the code example a bit to suit your requirement more. @Kevin Brock: If it is not required, then the OP would not have asked for "abstract variables". The difference in your example is that you don't show the requirement during compiletime.
BalusC
@Kevin: in every *instance*? I think we look at things through different glasses.
BalusC
Yes, every one. You have `this.bar` variable set to the value passed in the constructor. The local bar (instance) variable holds a reference to the passed in String. The String itself may only exist once (interned literal or static). But there is still the field holding the reference - in Java this is at least a 32-bit value in every instance.
Kevin Brock
@Kevin: Oh, that way. Well, that's a bit microoptimization. My way at least requires less repeated code and less things to take into account.
BalusC
+1  A: 

Just add this method to the base class

public abstract class clsAbstractTable {

    public abstract String getTAG();
    public abstract void init();

}

Now every class that extends the base class (and does not want to be abstract) should provide a TAG

You could also go with BalusC's answer

Lombo
That's not a solution. The solution starts with finding out what the OP wants to achieve.
Joachim Sauer
I edited my questions, I hope it's clear what I want to achieve.
Pentium10
I think this is the solution. At least the only one that Java provides that meets all of the requirements. Every subclass will have to provide a getTAG implementation that can return a string constant for that subclass. In my opinion, this is even better than keeping it around in a per-instance variable as in the original code.
PSpeed
I would discourage putting get/set in interface like this.
duffymo
@Joachim: that seems a bit harsh. I think Lombo understood the OP quite well and the getter method really is the better implementation, just not fully worked out here.
Kevin Brock
@duffymo: why discourage this? A getter is really what the OP is after since that is the most like C# properties (what he seem to be really thinking of). This also requires that a sub-class implement the getter - just as the OP was requesting.
Kevin Brock
@Kevin: it seems the OP wanted a "abstract static" variable (whatever that is) and the given suggestion doesn't solve that either.
Joachim Sauer
@Kevin, I don't think get/set belongs in interfaces, regardless of what the OP asked for. And I don't believe it requires a subclass getter/setter.
duffymo
+2  A: 

The best you could do is have accessor/mutators for the variable.
Something like getTAG()
That way all implementing classes would have to implement them.

Abstract classes are used to define abstract behaviour not data.

Padmarag
Yeah, I want to define abstract behavior, I mean to define the name, then I will deal with the data at the implementation level.
Pentium10
+1  A: 

Why do you want all subclasses to define the variable? If every subclass is supposed to have it, just define it in the superclass. BTW, given that it's good OOP practice not to expose fields anyway, your question makes even less sense.

ammoQ
+1  A: 

Change the code to:

public abstract class clsAbstractTable {
  protected String TAG;
  public abstract void init();
}

public class clsContactGroups extends clsAbstractTable {
  public String doSomething() {
    return TAG + "<something else>";
  }
}

That way, all of the classes who inherit this class will have this variable. You can do 200 subclasses and still each one of them will have this variable.

Side note: do not use CAPS as variable name; common wisdom is that all caps identifiers refer to constants, i.e. non-changeable pieces of data.

dimitko
When I create a new Class, will I be prompted to define the TAG for that class too?
Pentium10
*As some have reminded, you should never have public fields/variables in your classes* -- There is nothing wrong with `public final` fields in `public final class`, just a matter of taste.
Alexander Pogrebnyak
After reading the OP's second edit, I believe he is looking for OOP mechanisms on class level, which is not supported by Java. You can do all the OOP you want with *instance* methods, however not with *class* (`static` in Java) methods. You will either have to (1) live with the fact that every *instance* will have its own copy of the variable, or (2) make a global HashMap to contain mappings between class names and the values of TAG on a per-class basis. Both of which are imperfect, but hey, nobody said Java understands English. ;)
dimitko
+4  A: 

I think your confusion is with C# properties vs. fields/variables. In C# you cannot define abstract fields, even in an abstract class. You can, however, define abstract properties as these are effectively methods (e.g. compiled to get_TAG() and set_TAG(...)).

As some have reminded, you should never have public fields/variables in your classes, even in C#. Several answers have hinted at what I would recommend, but have not made it clear. You should translate your idea into Java as a JavaBean property, using getTAG(). Then your sub-classes will have to implement this (I also have written a project with table classes that do this).

So you can have an abstract class defined like this...

public abstract class AbstractTable {

    public abstract String getTag();
    public abstract void init();

    ...
}

Then, in any concrete subclasses you would need to define a static final variable (constant) and return that from the getTag(), something like this:

public class SalesTable extends AbstractTable {

    private static final String TABLE_NAME = "Sales";

    public String getTag() {
        return TABLE_NAME;
    }

    public void init() {
        ...
        String tableName = getTag();
        ...
    }

}

EDIT:

You cannot override inherited fields (in either C# or Java). Nor can you override static members, whether they are fields or methods. So this also is the best solution for that. I changed my init method example above to show how this would be used - again, think of the getXXX method as a property.

Kevin Brock
+1 I think this really answers the OP's question, as the original premise of the question is wrong (that C# can have abstract fields)
JonoW
A: 

To add per-class metadata, maybe an annotation might be the correct way to go.

However, you can't enforce the presence of an annotation in the interface, just as you can't enforce static members or the existence of a specific constructor.

Joachim Sauer