I have an abstract class that should implement a public field, this field is an interface or another abstract classe.
something like this:
public abstract class GenericContainer {
public GenericChild child;
}
public abstract class GenericChild {
public int prop1=1;
}
public abstract class SpecialChild extends GenericChild {
public int prop1=2;
}
Now i have another specialized class Container:
public abstract class SpecialContainer extends GenericContainer {
public SpecialChild child=new SpecialChild(); //PAY ATTENTION HERE!
}
Java allow me to compile this, and i IMAGINE that the field child in SpecialContainer is automatically overloading the field child of the GenericContainer...
The questions are:
Am i right on this? The automatic 'overloading' of child will happen?
And, more important question, if i have another class like this:
public class ExternalClass {
public GenericContainer container=new SpecialContainer();
public int test() {
return container.child.prop1
}
}
test() will return 1 or 2? i mean the GenericContainer container field what prop1 will call, the generic or the special?
And what if the special prop1 was declared as String (yes java allow me to compile also in this case)?
Thanks!
In Java, data members/attributes are not polymorphic. Overloading means that a field will have a different value depending from which class it's accessed. The field in the subclass will hide the field in the super-class, but both exists. The fields are invoked based on reference types, while methods are used of actual object. You can try it yourself.
It's called, variable hiding/shadowing, for more details look on here
It isn't overriding anything, you're just hiding the original field at the current class scope. If you use a variable with the subtype you will still be able to access the original property. Example:
abstract class GenericContainer {
public GenericChild child;
}
abstract class GenericChild {
public int prop1=1 ;
}
class SpecialChild extends GenericChild {
public int prop1=2;
}
class SpecialContainer extends GenericContainer {
public SpecialChild child;
}
public class Main {
public static void main( String ... args ) {
GenericContainer container = new SpecialContainer();
container.child = new SpecialChild();
System.out.println( container.child.prop1 );
SpecialChild child = (SpecialChild) container.child;
System.out.println( child.prop1 );
}
}
This prints 1 and then 2.
From SpecialChild you would also be able to go up one level using super:
class SpecialChild extends GenericChild {
public int prop1=2;
public int getOriginalProp1() {
return super.prop1;
}
}
Regarding
....and i IMAGINE that the field "child" in SpecialContainer is automatically overloading the field 'child' of the GenericContainer...
No. Fields don't get overridden, only methods do.
This is one reason why use of (overridable) getter and setter methods are preferred to direct access to fields. Your fields should almost all be private.
As for your design, there's no need for your SpecialContainer class to have a SpecialChild field, but instead the SpecialChild object should be placed in the GenericChild field.
Why nobody is observing that program will throw NullPointerException.
subclass's field with same name will hide super class's field. There is no overriding with field. Overriding is only possible with methods.
Original Code by Author:
public abstract class GenericContainer {
public GenericChild child;
}
public abstract class GenericChild {
public int prop1=1;
}
public abstract class SpecialChild extend GenericChild {
public int prop1=2;
}
public abstract class SpecialContainer extends GenericContainer {
public SpecialChild child=new SpecialChild(); //PAY ATTENTION HERE!
}
public class ExternalClass {
public GenericContainer container=new SpecialContainer();
public int test() {
return container.child.prop1
}
}
Java allow me to compile this, and i IMAGINE that the field "child" in
SpecialContainer is automatically overloading the field 'child' of the
GenericContainer...
Firstly, Inheritence doesn't apply to variables. Fields(Insatnce variables) are not overridden in your sub-class.they are only visible in your subclass if they are marked with either public, protected or default.
To answer your question it maintains both instances. And depending on how you refer to the container (either through the abstract or the impl) determines which variable you are referring to.
public class Test {
public abstract class Container{
public Generic gen = new Generic();
}
public class ContainerImpl extends Container{
public GenericImpl gen = new GenericImpl();
}
public class Generic{
public int prop = 0;
}
public class GenericImpl extends Generic{
public int prop = 1;
}
public Test(){
Container c = new ContainerImpl();
System.out.println(c.gen.prop); // Outputs "0"
System.out.println(((ContainerImpl)c).gen.prop); // Output "1"
}
public static void main(String[] args) {
new Test();
}
}
The bigger question at hand is, why would you design something like this? I'm assuming you are asking from a theoretical perspective.
My 2 cents, this isn't great OO design. You would be better off making the public variables private and assigning their values through a constructor or property setter. As-is, it will lead to unexpected results in your code.
Related
OK, so I'll start this with an example:
Let's say we have an abstract class with an interface variable, which is initialized in the constructor. The abstract class itself has a getter for that variable, it's subclasses have implementations of the interface in the constructor.
Now, the problem I'm getting is that when trying to call the getter of any of the subclasses (which is only declared in the superclass, but it should use the variable declared in their constructors) it doesn't return the implementation, it returns the interface itself.
public abstract class AbstractClass {
private final ExampleInterface exampleInterface;
public AbstractClass(ExampleInterface exampleInterface) {
this.exampleInterface = exampleInterface;
}
public ExampleInterface getExampleInterface() {
return this.exampleInterface;
}
}
public class AbstractClassSubclass extends AbstractClass {
//Instead of the interface itself, I provide my constructor it's implementation
public AbstractClassSubclass(ExampleInterfaceImplementation exampleInterfaceImpl) {
super(exampleInterfaceImpl);
}
}
public class TestClass {
private void testMethod() {
AbstractClassSubclass test = new AbstractClassSubclass(
new ExampleInterfaceImplementation()
);
//Would return ExampleInterface, instead of ExampleInterfaceImplementation
test.getExampleInterface();
}
}
Update
I believe I have fixed this using type parameters.
I'm sure I have tried it before but had a few problems...
Now it works perfectly.
I have an identical method that is repeated in every subclass and I'd like to refactor it to just one method in a superclass.
public class SubClass1 extends SuperClass {
private BoltHexHead bolt;
private void computeFoo() {
//Foo formula is identical in all subclasses. Need to move up
setFoo(bolt.getDiameter() + bolt.getPitch() + bolt.getTpi());
}
private void computeBar() {
//computeBar method in all subclasses but Bar formula is different amongst all subclasses
setBar(bolt.getDiameter() - 2*bolt.getPitch() - 3*bolt.getTpi());
}
private void computeSeparation() {
//computeSeparation method only exists for a Subclass 1
setSeparation(bolt.getLength() - 2*nut.getFlatDia());
}
public class SubClass2 extends SuperClass {
private BoltFlatHead bolt;
private void computeFoo() {
//Foo formula is identical in all subclasses. Need to move up
setFoo(bolt.getDiameter() + bolt.getPitch() + bolt.getTpi());
}
private void computeBar() {
//computeBar method here is different than in Subclass1
setBar(bolt.getDiameter() - 4*bolt.getPitch() - 1/3*bolt.getTpi());
}
private void computeProtrusion() {
//computeProtrusionmethod only exists for a Subclass 2
setProtrusionmethod(bolt.getThreadAngle() - 6*bolt.getTpi());
}
Initially I posted that bolt wasn't getting set in the SuperClass but was in the SubClass. What I got working after my initial post was the following
public abstract class SuperClass {
protected Bolt<?> bolt; <-- this was added but uses wildcard
...bolt getters/setter
protected void computeFoo() {
//Foo formula pulled up from all subclasses
setFoo(bolt.getDiameter() + bolt.getPitch() + bolt.getTpi());
}
}
public class SubClass1 extends SuperClass {
//private BoltHexHead bolt; <-- commented this out in each subclass
}
This is a JSF app and in each controller bean I instantiate the specific joint attribute subclass and then set the specific bolt. It was an earlier design decision to use setters for setting the bolt (and other properties) in the subclass rather than doing it with the Constructor; but one refactor at a time.
Controller for a Bolt Analysis using a HexHead Bolt
private SubClass1 sc1 = new SubClass1();
private BoltHexHead bolt;
sc1.setBolt(bolt);
sc1.computeResults();
Controller for a Bolt Analysis using a FlatHead Bolt
private SubClass2 sc2 = new SubClass2();
private BoltFlatHead bolt;
sc2.setBolt(bolt);
sc1.computeResults();
So my question is, is it OK to use wildcard Bolt<?> bolt or is there a better approach?
I'm just trying to put a identical/duplicate method from all my subclasses into the parent but one of the variables (bolt) isn't getting set
Thats because in java you cannot override fields.
So your variables "private B bolt;" in your superclass and "private BoltHexHead bolt;" in your subclass are two different things. They actually both exist at the same time.
What you are trying to do actually isn't that complicated. You just need to clean up your code:
Only define "private B bolt;" and its setters/getters once in your superclass.
Only use those getters/setters to access bolt
If you want your subclass to have a "bolt" of the type "BoltHexHead" then define the generic parameter as such in the class definition ("extends JointAttribute<BoltHexHead>" instead of "extends JointAttribute<Bolt<BoltSpec>>")
A simple example for demonstration purspose:
Superclass:
public class Superclass<T> {
private T value;
protected T getValue() {
return value;
}
protected void setValue(T value) {
this.value = value;
}
protected void print() {
if(getValue()==null) {
System.out.println("NULL");
} else {
System.out.println(getValue().toString());
}
}
}
Subclass1:
public class Subclass extends Superclass<String> {
public Subclass() {
}
public static void main(String[] args) {
Subclass subclass= new Subclass();
subclass.print();
subclass.setValue("test");
subclass.print();
}
}
Subclass2:
public class Subclass2 extends Superclass<Integer> {
public Subclass2() {
}
public static void main(String[] args) {
Subclass2 subclass= new Subclass2();
subclass.print();
subclass.setValue(3);
subclass.print();
}
}
I thought I understood how to use .class and Class<> but I guess not. The below super(ApprovalWorkstation.class is not being mapped to the constructor. How can I be sure that I'm passing a class reference so that the base WorkstationRequest can instantiate it?
public class ApprovalWorkstation extends Workstation {
public ApprovalWorkstation(WorkstationEntity entity) {
super(entity);
}
}
public class WorkstationRequest extends com.production.socket.request.WorkstationRequest {
public WorkstationRequest() {
super(ApprovalWorkstation.class); //unable to map to constructor
}
}
This is the base WorkstationRequest that's extended above
public class WorkstationRequest {
private Class<Workstation> workstationClass;
public void WorkstationRequest(Class<Workstation> workstationClass) {
this.workstationClass = workstationClass;
}
update
I'm sorry for the confusion, my constructor actually has Class<Workstation> and not Workstation as I initially had.
In order to be able to pass both Workstation class and it's child classes you should change definition of WorkstationRequest to the following:
public class WorkstationRequest {
private Class<? extends Workstation> workstationClass;
public WorkstationRequest(Class<? extends Workstation> workstationClass) {
this.workstationClass = workstationClass;
}
}
Correct me if I am wrong, but you are passing in a Workstation instance while what needed is a Class<Workstation>. Maybe use workstationClass.getClass() instead?
You're trying to assign an instance of Worstation to field of type Class<Workstation> which is obviously not the same.
What you're probably trying to do is:
public WorkstationRequest(Class<Workstation> workstationClass) {
Of course there is no return type (void) in constructors. Your "constructor" is simply a method:
public void WorkstationRequest(Class<Workstation> workstationClass) { // method
public WorkstationRequest(Class<Workstation> workstationClass) { // constructor
There is no constructor that takes a Class as a parameter in the base WorkstationRequest class.
Constructors do NOT have a return type, so public void WorkstationRequest needs to be changed to public WorkstationRequest.
So I've come across a bit of a snag in some code that I'm working with. Essentially I have the following three tidbits of code:
Abstract class:
public abstract class TestParent {
int size;
public TestParent(int i){
size = i;
}
}
Child Class:
public class TestChild extends TestParent{
public void mult(){
System.out.println(this.size * 5);
}
}
Implementation:
public class TestTest {
public static void main(String args[]) {
TestChild Test = new TestChild(2);
Test.mult();
}
}
Consider the following case of abstract class and extends implementation.
https://stackoverflow.com/a/260755/1071979
abstract class Product {
int multiplyBy;
public Product( int multiplyBy ) {
this.multiplyBy = multiplyBy;
}
public int mutiply(int val) {
return muliplyBy * val;
}
}
class TimesTwo extends Product {
public TimesTwo() {
super(2);
}
}
class TimesWhat extends Product {
public TimesWhat(int what) {
super(what);
}
}
The superclass Product is abstract and has a constructor. The concrete class TimesTwo has a default constructor that just hardcodes the value 2. The concrete class TimesWhat has a constructor that allows the caller to specify the value.
NOTE: As there is no default (or no-arg) constructor in the parent abstract class the constructor used in subclasses must be specified.
Abstract constructors will frequently be used to enforce class constraints or invariants such as the minimum fields required to setup the class.
public class TestChild extends TestParent{
public TestChild(int i){
super(i); // Call to the parent's constructor.
}
public void mult(){
System.out.println(super.size * 5);
}
}
Use super to call parent (TestParent.TestParent(int)) constructor:
public class TestChild extends TestParent{
public TestChild(int i) {
super(i);
}
//...
}
or if you want to use some constant:
public TestChild() {
super(42);
}
Note that there is no such thing as abstract constructor in Java. Essentially there is only one constructor in TestParent which must be called before calling TestChild constructor.
Also note that super() must always be the first statement.
When you have explicit constructor defined in super class and no constructor without arguments defined, your child class should explicitly call the super class constructor.
public class TestChild extends TestParent{
TestChild ()
{
super(5);
}
}
or, if you don't want call super class constructor with parameters, you need to add constructor with no arguments in super class.
public abstract class TestParent {
int size;
public TestParent(){
}
public TestParent(int i){
size = i;
}
}
You code wont compile because your base class does not have a default constructor. Either you need to provide it in base class or you need to provide parameterized constructor in derived class and invoke super.
public class TestChild extends TestParent{
public TestChild (int i)
{
super(i * 2);
}
}
This code would use the double of i. This is an overriding, though i'm not sure what you want to ask.
Other solution:
public class TestChild extends TestParent{
public TestChild (int i)
{
super(i);
this.size = 105;
}
}
For this solution, size must be protected or public.
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).