Passing a subclass to a method with an abstract class parameter - java

I've been trying to understand what is happening with this example, but haven't been able to so far. Can anyone help?
Say I have these two Abstract classes:
public abstract class AbstractBook<T extends AbstractPage> implements Serializable{
public AbstractBook() {
}
public abstract void addPage(T var1);
}
and
public abstract class AbstractPage implements Serializable {
public AbstractPage() {
}
}
And classes that are extended like these:
public class Book extends AbstractBook {
private ArrayList<Page> allPages;
private String title;
Book(String title){
allPages = new ArrayList<Page>();
}
#Override
public void addPage(AbstractPage page) {
this.allPages.add();
}
}
and
public class Page extends AbstractPage {
private String content;
public Page(String Content){
this.content = Content;
}
}
In the Book class there is a method called addPage. I can pass a Page class object to this method, however; I can't add that object to the ArrayList<Page> allPages.
Why exactly is that? I mean I think it is because the compiler expects type AbstractPage instead of Page. But why then I am capable of calling the method like thisbook.addPage(pageObject) ?
So In other words, it lets me pass a subclass object, but it doesn't let me do anything with that passed object.
And how do you get around this so that I can add that pageObject to the ArrayList<Page> allPages structure?

You can make it work by modifying your Book class:
public class Book extends AbstractBook<AbstractPage> {
private ArrayList<AbstractPage> allPages;
private String title;
Book(String title){
allPages = new ArrayList<AbstractPage>();
}
#Override
public void addPage(AbstractPage page) {
this.allPages.add(page);
}
}
You should use the type parameter of AbstractBook when defining the class Book. The ArrayList has to bee of type AbstractPage if you want to insert elements of this type.

You can't add AbstractPage to list of Pages, because Page is one level up in terms of inheritance from AbstractPage: Object <- AbstractPage <- Page. If you want to add Pages to your list, you have to extend AbstractBook<Page>:
public class Book extends AbstractBook<Page> {
private ArrayList<Page> allPages;
private String title;
Book(String title){
allPages = new ArrayList<Page>();
}
#Override
public void addPage(Page page) {
this.allPages.add();
}
}

Related

Giving the object to create as parameta in constuctor

sorry for the title I don't know how to say that.
So basically what I want to do is the following:
public class TestClass {
private final String name;
public TestClass(String name) {
this.name = name;
}
public TestClass(TestClass test) {
this = test;
}
public String getName() {
return name;
}
}
So create a class where you can give an object from itself in the constructor
I don't know if that is possible at all.
The problem I have is that I have multiple objects that extend from this class and I want a simple way to pass them to the next class
so when I have 2 classes
TestClass2 extends TestClass
TestClass3 extends TestClass
and I want to create an instance of the testclass3 from the testclass2 one.
they both should have the same name from testcalss
currently, I am doing that like that:
private class TestClass2 extends TestClass{
private final String anotherName;
public TestClass2(String name, String anotherName) {
super(name);
this.anotherName= anotherName;
}
private void createTest3(String whatever) {
new TestClass3(this, whatever);
}
}
private class TestClass3 extends TestClass{
private final String whatever;
public TestClass3(TestClass test, String whatever) {
super(test.getName());
this.whatever = whatever;
}
}
In my case, my base class has not just a name but a lot more values that I then have to submit!
I hope you kinda understand what I want to say. Again sorry I explained that very bad :D
And thank you all thanks in advance for any answers!

Confused by <T extends Class> behavior

So I have this AbstractBook Class
public abstract class AbstractBook<T extends AbstractPage> implements Serializable{
public AbstractBook() {
}
public abstract void addPage(T var1);
}
and I have a sub class:
public class Book extends AbstractBook {
private ArrayList<Page> allPages;
private String title;
Book(String title){
allPages = new ArrayList<Page>();
}
#Override /** Doesn't Work */
public void addPage(Page page) {
this.allPages.add();
}
}
In the subclass addPage method, I can't Override the method in the given form, because the parameter asks to be an AbstractPage type, even though Page is extended from AbstractPage:
public abstract class AbstractPage implements Serializable {
public AbstractPage() {
}
}
and
public class Page extends AbstractPage {
private String content;
public Page(String Content){
this.content = Content;
}
}
Why is that exactly?
Isn't T defined as <T extends AbstractPage>, thus, Page should be an acceptable type for the parameter in addPage method ? It insists on compiler insists on AbstractPage type.
Or does <T extends AbstractPage> not actually apply to the T var1
in the addPage method ?
But even then, what stops addPage(Page page) method from compiling?
You are extending a raw type.
Change
public class Book extends AbstractBook
to
public class Book extends AbstractBook<Page>
Besides, this.allPages.add(); should probably be this.allPages.add(page);.

meaning of "public interface MyInterface<T extends MyInterface<T>> {...}"

I have just come across a piece of code which does:
public interface MyInterface<T extends MyInterface<T>> {...}
Then classes seem to do:
public final class MyClass implements MyInterface<MyClass> {...}
The interface has no definitions, only method declarations. I think extends MyInterface<T> is redundant and the interface can be just:
public interface MyInterface<T> {...}
Being new to Java, is there any purpose of the original interface definition (with the extends part)? Is this a pattern?
The interface has no definitions, only method declarations. I think extends MyInterface is redundant...
No it's not. The bound ensures that only Classes are accepted that implement this interface as well. Let's take a look at an interface:
SomeInterface.java
public interface SomeInterface<T extends SomeInterface<T>>
{
public T getInterfaceImpl();
public void setTitle(String text);
}
and two differnet implementing classes:
SomeInterfaceImpl.java:
public class SomeInterfaceImpl implements SomeInterface<SomeInterfaceImpl>
{
private String title;
#Override
public SomeInterfaceImpl getInterfaceImpl()
{
return new SomeInterfaceImpl();
}
#Override
public void setTitle( String text )
{
this.title = text;
}
}
and AnotherSomeInterfaceImpl.java:
public class AnotherSomeInterfaceImpl implements SomeInterface<SomeInterfaceImpl>
{
private String title;
#Override
public SomeInterfaceImpl getInterfaceImpl()
{
return new SomeInterfaceImpl();
}
#Override
public void setTitle( String text )
{
this.title = text;
}
}
Take a precise look at the method signature in both implementations. Both classes extend the same interface with the same type parameter which defines the signature of the methods in the same way. Imagine omitting the bound in the interface delcaration. Suddenly an implementing class could look like this:
public class AnotherSomeInterfaceImpl implements SomeInterface<String>
{
private String title;
#Override
public String getInterfaceImpl()
{
return "Hello World";
}
#Override
public void setTitle( String text )
{
this.title = text;
}
}
And now we are no longer assured that the returned object of public T getInterfaceImpl() is an implementation of SomeInterface or that it has methods like public void setTitle(String text).

Overriding Abstract Fields Java

I have an abstract class which has a method used by all classes that extend the class. That method is identical for each class so I don't want to have to write it over and over in those classes. The problem is that the method uses 2 variables that are declared in each class. I can't have the method in the abstract class without having those variables int eh abstract class. But if I do that, they take on the value specified in the abstract class, not the classes that extend it. How can I fix this?
Example code:
public abstract class Example {
public String property1 = ""
public String property2 = ""
public ArrayList<String> getPropertyies() {
ArrayList<String> propertyList = new ArrayList<>();
propertyList.add(property1);
propertyList.add(property2);
return property1;
}
}
public class ExampleExtension extends Example {
public String property1 = "this is the property";
public String property2 = "this is the second property";
}
You should limit the scope of the fields to private in the abstract class and declare a constructor for populating the values:
public abstract class Example {
private final String property1;
private final String property2;
protected Example(String property1, String property2) {
this.property1 = property1;
this.property2 = property2;
}
//...
}
Subclasses would then initialize the field values in their constructors by calling the super constructor:
public class ExampleExtension extends Example {
public ExampleExtension() {
super("value1", "value2");
// initialize private fields of ExampleExtension, if any
}
// ...
}
You don't have to override the variables. You can set the initial values of your properties in the constructor:
public class ExampleExtension extends Example {
public ExampleExtension() {
property1 = "this is the property";
property2 = "this is the second property";
}
}
A better way is to use a constructor with parameters though, as Mick Mnemonic suggest in the other answer.
IMO Mick's solution is the most pragmatic, although note that you also have the option to make the properties abstract, and then use subclass polymorphicism to require that subclasses override the property implementation:
public abstract class Example {
public abstract String getProperty1();
public abstract String getProperty2();
public ArrayList<String> getPropertyies() {
ArrayList<String> propertyList = new ArrayList<>();
propertyList.add(getProperty1());
propertyList.add(getProperty2());
return propertyList;
}
}
public class ExampleExtension extends Example {
public String getProperty1() { return "this is the property"};
public String getProperty2() { return "this is the second property"};
}
Make what differs(e.g. property1,property2) abstract method in this case . Search for related reading on template pattern
public abstract class Example {
public ArrayList<String> getPropertyies() {
ArrayList<String> propertyList = new ArrayList<>();
propertyList.add(getProperty1());
propertyList.add(getProperty2());
return property1;
}
public abstract getProperty1();//overriden by other class that has diff value for property1
public abstract getProperty2();//overriden by other class that has diff value for property2
}

NoSuchFieldError when extending Interface in generic class

I have a bean ArtistEntityBean extending GenericEntityBean:
public class ArtistEntityBean extends GenericEntityBean<Artist> {
public ArtistEntityBean() {
item = new Artist();
}
}
-
public abstract class GenericEntityBean<T extends IntEntity> implements Serializable {
protected T item;
public void init(Integer id){
item.setId(id);
}
}
-
public class Artist extends ArtistBaseEntity implements Comparable<Artist> {
...
}
-
public abstract class ArtistBaseEntity implements IntEntity {
...
}
-
public interface IntEntity {
Integer getId();
void setId(Integer id);
}
-
I'm trying to put as much code as possible in the GenericEntityBean class, which is why I thought of using an interface in order to be able to set the id of the item.
This does not work tough, as I get a NoSuchFieldError in the constructor of ArtistEntityBean and I don't know why?
If item is public, protected or default you have to use
super.item = new Artist();
in the constructor of ArtistEntityBean.
If it is private you have to provide a setter method in the abstract class.
Edit: If you did not specify item in the abstract class then do the following
public abstract class GenericEntityBean<T extends IntEntity> implements Serializable {
protected T item;
public void init(Integer id){
item.setId(id);
}
}

Categories