I have a class Parent and a class Derived like
class Parent {
SomeClass obj = new SomeClass();
}
Now below class i want to generate using CodeModel
class Derived extends Parent {
String s = obj.invoke();
}
I tried below but not working
tryBlock.body().decl(codeModel.ref(String.class), "s",
(codeModel.ref(Parent.class)).staticRef("obj").invoke("invoke"));
How can I invoke obj rather than creating a new object as I am doing in Parent class?
You could give the Parent class a protected attribute of the type SomeClass and use it directly in the Derived class:
public class Parent {
protected SomeClass someObject;
public Parent() {
this.someObject = new SomeClass();
}
}
public class Derived extends Parent {
public void printInvoked() {
System.out.println(this.someObject.invoke());
}
}
public class SomeClass {
public String invoke() {
return "SomeClass invoked";
}
}
You can reference the field directly using JExpr.ref() and use it to initialize the field:
JDefinedClass derived = codeModel._class(JMod.PUBLIC, "Derived", ClassType.CLASS);
derived._extends(Parent.class);
derived.field(0, String.class, "s", JExpr.ref("obj").invoke("invoke"));
This generates the following:
public class Derived
extends Parent
{
String s = obj.invoke();
}
Related
I have a parent class
public class Parent
{
Database m_d;
Parent(Database d){
m_d = d;
}
}
And a child class
public class Child extends Parent implements java.lang.AutoCloseable
{
ChildDatabase m_d
Child()
{
// Error on the next statement:
// "Cannot reference m_database before supertype constructor
// has been called"
super(m_d = CreateDatabase());
}
}
Note that ChildDatabase implements java.lang.AutoCloseable which is a reason why I need to keep a ChildDatabase reference in the Child class. Note that ChildDatabase extends Database.
The problem is that super(m_d = CreateDatabase()); is not valid since you can't refer to child class members in the call to super.
Is there a syntax I'm missing which would allow me to do this? An alternative would be to implement a getDatabase() method in Parent, and cast that result to a ChildDatabase to store as m_d;, but that seems a smell to me.
Note that CreateDatabase can be static.
How about
public abstract class Parent<DB extends Database>
{
DB m_d;
Parent()
{
m_d = getDatabase();
}
abstract DB getDatabase();
}
and
public class Child extends Parent<ChildDatabase> implements java.lang.AutoCloseable
{
Child()
{
// do something with this.m_d here
}
#Override
ChildDatabase getDatabase()
{
return createChildDatabase();
}
}
Then you can even use AutoCloseable features directly on this.m_d (like try...with etc).
What you are trying to achieve is simply not feasible.
Following the Java language specification, no class field member can be initialized before the call to super (constructor) has been done.
As you are implementing a specific behavior within your Child class, a workaround, may be to omit the local m_d field passing the desired Database instance reference over a factory mixed with a generic formal type for the sub-type Database.
Here down the Parent class type:
public class Parent<D extends Database> {
D m_d;
Parent(D m_d) {
m_d = m_d;
}
protected D getDatabase() {
return this.m_d;
}
}
And the Child would be as follows:
public class Child extends Parent<ChildDatabase> {
private Child(ChildDatabase m_d) {
super(m_d);
}
private static ChildDatabase createDatabase() {
return null;
}
public static class ChildFactory {
public static Child createChild() {
return new Child(createDatabase());
}
}
}
Why do you want to have the field m_d in both Parent and Child? Isn't it sufficient to have it only in Parent? And simply have super(createDatabase()); in Child's constructor like in below code:
public class Parent
{
Database m_d;
Parent(Database d)
{
m_d = d;
}
}
class Child extends Parent implements java.lang.AutoCloseable
{
Child()
{
super(createDatabase());
}
private static ChildDatabase createDatabase()
{
return new ChildDatabase();
}
#Override
public void close() throws Exception
{
}
}
class Database
{
}
class ChildDatabase extends Database implements java.lang.AutoCloseable
{
#Override
public void close() throws Exception
{
}
}
By introducing a getter of the object in the parent class you could write it :
public class Child extends Parent implements java.lang.AutoCloseable
{
ChildDatabase m_d;
Child()
{
// Error on the next statement:
// "Cannot reference m_database before supertype constructor
// has been called"
super(CreateDatabase());
this.m_d = (ChildDatabase)getMd();
}
}
But the downcast is undesirable, it may fail at runtime and it looks a hack.
If the subclass needs to refer to the field as a ChildDataBase, it should be explicit in the constructor itself such as :
ChildDatabase m_d;
Child(ChildDatabase childDb)
{
super(childDb);
m_d = childDb;
}
In a general way dependencies should be explicit if not an implementation detail since It favors the testability and the switch to other implementations.
Note that I don't like either a lot this solution.
This still duplicates the field in the hierarchy.
The problem here is that you want to value the same object with for the parent constructor and the child constructor a distinct declared type.
You should not. It is error prone for people reading your code.
Using a generic class is probably better and would allow subclasses to specify the subclass for Database fields.
It will still require to provide the getter in the parent class.
public class Parent<T ? extends DataBase>
{
private T m_d;
Parent(T d){
m_d = d;
}
public T getMd(){
return m_d;
}
}
With hidden dependency :
public class Child extends Parent<ChildDataBase> implements AutoCloseable
{
Child(){
super(CreateDatabase());
}
void foo(){
ChildDataBase md = getMd(); // return the generic type
}
}
With exposed dependency :
public class Child extends Parent<ChildDataBase> implements AutoCloseable
{
Child(ChildDataBase md){
super(md);
}
void foo(){
ChildDataBase md = getMd(); // return the generic type
}
}
public class Parent {
....
}
public class Child1 extends Parent {
....
public void foo() {
....
}
}
public class Child2 extends Parent {
....
public void foo() {
....
}
}
Here method foo() only exists in the Child classes and CAN NOT be added to the Parent class (not even abstract method). In this situation when I want to call the foo() method on obj which is Parent class's reference then I need to use intanceof with multiple if..else which I want to avoid.
Parent obj = ...// Object of one of the child classes
obj.foo();
EDIT: I Need to use type of obj as Parent only. Else I will not be able to call methods on obj which exists in Parent class.
My Solution: The approach that I am thinking is to define an interface say FooInterface with foo() method and let all the child classes implement it, then I could just type cast the obj to that interface and call foo() method like this:
if(obj instanceof FooInterface){
((FooInterface)obj).foo();
}
Is there a better approach ? Or any improvement to this one?
You can't do it with parent object reference until an unless method is declared in parent class/interface itself.
You have to downcast it to child class because parent class/interface doesn't have any knowledge about the child class other than the contract defined between them.
Here contract means abstract methods.
you can try in this way where there is no need to put a check it.
FooInterface sc =new Child1();
sc.foo();
...
interface FooInterface{
void foo();
}
public class Parent {
}
public class Child1 extends Parent implements FooInterface{
public void foo() {
}
}
public class Child2 extends Parent implements FooInterface{
public void foo() {
}
}
The approach that I am finally taking is to define an interface say FooInterface with foo() method and let all the child classes implement it, then I could just type cast the obj to that interface and call foo() method like this:
Parent obj = ...// Object of one of the child classes
.....
if(obj instanceof FooInterface){
((FooInterface)obj).foo();
}
The polymorphism is applied on object reference, not a type. When you call
FooInterface obj = ...// Object of one of the child classes
obj.foo();
the child class method foo() is called.
If you want to typecast only then there is no need of adding interface. You can typecast it to your desired class and call the method. Example
public class HelloWorld {
public static void main(String args[]) throws FileNotFoundException {
SuperClass sc =new Child1();
if(sc instanceof Child1)//Do same for Child2
((Child1)sc).foo();
}
}
class SuperClass {
}
class Child1 extends SuperClass{
public void foo(){
System.out.println("From child1");
}
}
class Child2 extends SuperClass{
public void foo(){
System.out.println("From child2");
}
}
Output :
From child1
You could implement an AbstractChild inheriting from Parent and then extend this class instead of Parent:
public class Parent {
....
}
public abstract class AbstractChild extends Parent{
public abstract void foo();
}
public class Child1 extends AbstractChild {
....
public void foo() {
....
}
}
public class Child2 extends AbstractChild {
....
public void foo() {
....
}
}
So you need to only check if your instance is instanceof AbstractChild.
I have Builders within both a parent and subclass. The parent has an abstract builder and a concrete builder that extends the abstract builder. The child has an abstract builder that extends the parent abstract builder and a concrete builder that extends the child abstract builder. The reason for this is so the setters of the parent return the current Builder class. I have methods that return the class's own abstract builder type that I'd like to refer to as the parent abstract type (to call the parent methods on it). All I could get to work was ParentBuilder<? extends ParentBuilder<?>>, but that doesn't seem great because of the wildcards. Here is an example that maybe can explain it better.
What I want to do in my main code:
ParentBuilder<? extends ParentBuilder<?> builder; // How to do this?
if (something) {
builder = Child.doSomething();
}
else {
builder = new Parent.builder();
}
Parent p = builder.setThing1("foo").build();
In Parent.java
public class Parent {
private final String thing1;
protected <B extends ParentBuilder<B>> Parent(final B builder) {
this.thing1 = builder.thing1;
}
public String getThing1() {
return this.thing1;
}
protected abstract static class ParentBuilder<B extends ParentBuilder<B>> {
protected final Class<B> builderClass;
protected String thing1;
protected ParentBuilder(final Class<B> builderClass) {
this.builderClass = builderClass;
}
public B setThing1(final String thing1) {
this.thing1 = thing1;
return builderClass.cast(this);
}
public abstract Parent build();
}
public static class Builder extends ParentBuilder<Builder> {
public Builder() {
super(Builder.class);
}
#Override
public Parent build() {
return new Parent(this);
}
}
}
In Child.java
public class Child extends Parent {
private final String thing2;
protected <B extends ChildBuilder<B>> Child(final B builder) {
super(builder);
this.thing2 = builder.thing2;
}
public String getThing2() {
return this.thing2;
}
public static Builder doThings(/*...*/) {
//...
return new Child.Builder();
}
protected abstract static class ChildBuilder<B extends ParentBuilder<B>> extends ParentBuilder<B> {
protected String thing2;
protected ChildBuilder(final Class<B> builderClass) {
super(builderClass);
}
public B setThing2(final String thing2) {
this.thing2 = thing2;
return builderClass.cast(this);
}
}
public static class Builder extends ChildBuilder<Builder> {
public Builder() {
super(Builder.class);
}
#Override
public Child build() {
return new Child(this);
}
}
}
In the first section I declare the builder as the parent abstract builder type, but I'm not sure the right way to type that object. The wildcards don't seem right. One option I thought of was making an interface above the abstract builders, then I could use that type. But it seems cumbersome to have interface -> abstract class -> concrete class in the parent and each sub class. Does anyone have any other suggestions? Thank you.
Here is working code with the setup you have:
Parent.ParentBuilder<?> builder;
if ( something ) {
builder = new Child.Builder();
}
else {
builder = new Parent.Builder();
}
Parent p = builder.setThing1("foo").build();
Now if you want builder.build() to return Child without a cast you need to change your existing builder generic type declarations.
I try to instantiate the inner class defined in the following Java code:
public class Mother {
public class Child {
public void doStuff() {
// ...
}
}
}
When I try to get an instance of Child like this
Class<?> clazz= Class.forName("com.mycompany.Mother$Child");
Child c = clazz.newInstance();
I get this exception:
java.lang.InstantiationException: com.mycompany.Mother$Child
at java.lang.Class.newInstance0(Class.java:340)
at java.lang.Class.newInstance(Class.java:308)
...
What am I missing ?
There's an extra "hidden" parameter, which is the instance of the enclosing class. You'll need to get at the constructor using Class.getDeclaredConstructor and then supply an instance of the enclosing class as an argument. For example:
// All exception handling omitted!
Class<?> enclosingClass = Class.forName("com.mycompany.Mother");
Object enclosingInstance = enclosingClass.newInstance();
Class<?> innerClass = Class.forName("com.mycompany.Mother$Child");
Constructor<?> ctor = innerClass.getDeclaredConstructor(enclosingClass);
Object innerInstance = ctor.newInstance(enclosingInstance);
Alternatively, if the nested class doesn't actually need to refer to an enclosing instance, make it a nested static class instead:
public class Mother {
public static class Child {
public void doStuff() {
// ...
}
}
}
This code create inner class instance.
Class childClass = Child.class;
String motherClassName = childClass.getCanonicalName().subSequence(0, childClass.getCanonicalName().length() - childClass.getSimpleName().length() - 1).toString();
Class motherClassType = Class.forName(motherClassName) ;
Mother mother = motherClassType.newInstance()
Child child = childClass.getConstructor(new Class[]{motherClassType}).newInstance(new Object[]{mother});
I want some discussions about this, but I could not infer the answer for my case. Still need help.
Here is my code:
package JustRandomPackage;
public class YetAnotherClass{
protected int variable = 5;
}
package FirstChapter;
import JustRandomPackage.*;
public class ATypeNameProgram extends YetAnotherClass{
public static void main(String[] args) {
YetAnotherClass bill = new YetAnotherClass();
System.out.println(bill.variable); // error: YetAnotherClass.variable is not visible
}
}
Some definitions following which, the example above seems to be confusing:
1. Subclass is a class that extends another class.
2. Class members declared as protected can be accessed from
the classes in the same package as well as classes in other packages
that are subclasses of the declaring class.
The question: Why can't I access the protected member (int variable = 5) from a subclass YetAnotherClass instance (bill object)?
Classes in other packages that are subclasses of the declaring class can only access their own inherited protected members.
package FirstChapter;
import JustRandomPackage.*;
public class ATypeNameProgram extends YetAnotherClass{
public ATypeNameProgram() {
System.out.println(this.variable); // this.variable is visible
}
}
... but not other objects' inherited protected members.
package FirstChapter;
import JustRandomPackage.*;
public class ATypeNameProgram extends YetAnotherClass{
public ATypeNameProgram() {
System.out.println(this.variable); // this.variable is visible
}
public boolean equals(ATypeNameProgram other) {
return this.variable == other.variable; // error: YetAnotherClass.variable is not visible
}
}
bill is not part of the subclassed YetAnotherClass. bill is a separate YetAnotherClass.
Try int bill = this.variable; (inside a constructor) to access the subclass' members.
Your code will work if YetAnotherClass will be in the same package as ATypeNameProgram. As others wrote it won't work in other cases. Here is the working example.
package my.example;
public class MainClass extends MyAnotherClass {
public static void main(String[] args) {
MyAnotherClass bill = new MyAnotherClass();
System.out.println(bill.value); // this will work
}
}
package my.example;
public class MyAnotherClass {
protected int value = 5;
}
A class Foo can only access the protected instance members of type Bar if and only if Bar is assignable to Foo. I.e., if we can write:
Foo foo = new Bar();
For example, say we have:
package a;
public class Base {
protected int protectedField;
}
Then we can have this:
package b;
import a.Base;
public class Parent extends Base {
void foo() {
int i = this.protectedField;
}
void foo(Parent p) {
int i = p.protectedField;
}
void foo(Child c) {
int i = c.protectedField;
}
}
class Child extends Parent { }
This will compile because all protectedFields are accessed via instances of Parent. Note that because a Parent reference can be a Child instance (i.e., we can write Parent p = new Child();), we can access c.protectedField.
The following will not compile:
package b;
import a.Base;
public class Parent extends Base {
void foo(Stepchild sc) {
int i = sc.protectedField; // ERROR
}
}
class Stepchild extends Base {}
because an instance of Stepchild is not an instance of Parent.
Somewhat confusingly, this won't compile either:
package b;
import a.Base;
public class Parent extends Base {}
class Child extends Parent {
void foo(Parent p) {
p.protectedField; // ERROR
}
}
this is because a Parent object isn't a superclass or superinterface of Child, and so Child can't access its protected members.
If you ever have trouble remembering, just think of whether or not the type can be written to a reference of the type of the class. E.g., we can write:
Parent p = new Child();
but cannot write
Child c = new Parent(); // ERROR
Parent p = new Stepchild(); // ERROR
so Child won't have access to Parent's protected members, and Parent won't have access to Stepchild's protected members.
A couple final points:
Remember that protected access allows visibility among the package. In my experience, people forget this.
Finally, protected static members are always visible among the inheritance hierarchy.
You aren't creating an instance of the class that extend it, but of the parent class. Check the code below:
public class ATypeNameProgram extends YetAnotherClass{
public static void main(String[] args) {
YetAnotherClass bill = new YetAnotherClass();
System.out.println(bill.variable); // error: YetAnotherClass.variable is not visible
ATypeNameProgram a = new ATypeNameProgram();
System.out.println(a.variable); //this will work
}
}