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);.
Related
I have this Interface:
public interface Test<T> {
default Class<?> getT() {
return T.getClass(); < --error
}
}
next i have a class that implements it:
static class ItemService implements Test<Item>{
}
And i want to get the 'Item' class from the 'ItemService' class
static ItemService service = new ItemService();
private static void k() {
System.out.println(service.getT());
}
Now one way to do it is this:
public interface Test<T> {
default Class<?> getT() {
return Type.type;
}
class Type {
public static Class<?> type;
}
}
Service:
static class ItemService implements Test<Item> {
public ItemService() {
Type.type = Item.class;
}
}
And it works fine but there is a problem,
When another class implement the interface:
static class OrderService implements Test<Order> {
public OrderService() {
Type.type = Order.class;
}
}
And i try:
static ItemService service = new ItemService();
static OrderService orderservice = new OrderService();
private static void k() {
System.out.println(service.getT());
}
I get the Order class and not the Item class
How can i make it work?
Classes inside interfaces are static, You can remove the default from the function and every class will need to implement this. example:
public interface Test<T> {
public Class<T> getT();
}
static class ItemService implements Test<Item> {
public Class<Item> getT() {return Item.class;}
}
static class OrderService implements Test<Order>{
public Class<Order> getT() {return Order.class;}
}
An alternative could be an abstract class.
public interface Test<T> {
public Class<T> getT();
}
abstract class AbstractTest<T> implements Test<T> {
private final Class<T> type;
AbstractItemService(Class<T> type) { this.type = type }
public Class<T> getT() {return type;}
}
class ItemService extends AbstractTest<Item> {
ItemService() { super(Item.class); }
// implement other things
}
class OrderService extends AbstractTest<Order>{
OrderService() { super(Order.class); }
// implement other things
}
Here is another option, if your implementation has an instance of T.
interface Test<T>{
T getT();
default Class<?> getClassOfT(){
return getT().getClass();
}
}
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();
}
}
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).
I have the interface
public interface MyInterface {
public void myTask (ServiceHandler.SongInfo[] songInfo);
}
I have the ServiceHandler.SongInfo class
public class SongInfo {
public String wrapperType;
public String kind;
public Integer artistId;
public Integer collectionId
//etc
}
I have the decleration
public class MainActivity extends AppCompatActivity implements MyInterface {
//... Everything else
#Override
void myTask(SongInfo[] songInfo){
}
}
But I sill get the error unless I comment out this line in my interface
public interface MyInterface {
//public void myTask (ServiceHandler.SongInfo[] songInfo);
}
What does it mean?
Change songInfo[] to ServiceHandler.SongInfo[] in the implementation argument
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);
}
}