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

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).

Related

Passing a subclass to a method with an abstract class parameter

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();
}
}

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);.

implem is not abstract and does not override abstract method FinalScore() in extending interfaces

program 1
interface java{
public void setHomeTeam(String name);
public void setVisitingTeam(String name);
}
program 2
interface extension extends java {
public String HomeTeamScored();
public String VisitingTeamScored();
public String FinalScore();
}
program 3
public class implem implements extension{
private String Home;
private String Visit;
public String HomeTeamScored(){
return Home;
}
public String VisitingTeamScored(){
return Visit;
}
public void setHome(String Home){
this.Home = Home;
}
public void setVisit(String Visit){
this.Visit = Visit;
}
}
program 4
public class compilation{
public static void main(String [] args){
implem implement = new implem();
implement.setHome("Nihon");
implement.setVisit("Chuugoku");
System.out.println(""+implement.HomeTeamScored());
System.out.println(""+implement.VisitingTeamScored());
}
}
These are my programs for extending interfaces and I get the error:
implem is not abstract and does not override abstract method FinalScore() in extension
public class implem implements extension{
^
1 error
Process completed.
You can find a definition of a java's interface[site]
It says
If your class claims to implement an interface, all methods defined
by that interface must appear in its source code before the class will
successfully compile
So, your implem class must implement all interface methods from java and its child class extension.
Your implem class have to follow the rule so it looks like as follows,
public class implem implements extension {
private String Home;
private String Visit;
#Override
public String HomeTeamScored() {
return Home;
}
#Override
public String VisitingTeamScored() {
return Visit;
}
#Override
public void setHomeTeam(String name) {
}
public void setHome(String Home) {
this.Home = Home;
}
public void setVisit(String Visit) {
this.Visit = Visit;
}
#Override
public void setVisitingTeam(String name) {
}
#Override
public String FinalScore() {
return null;
}
}
Because you are implementing 'extension' you need to implement all the methods in the interface you need to add
Public String FinalScore();
To your class
Your non-abstract class implem is not implementing all the methods of interfaces. Public String FinalScore() is such one method.

MainActivity must be declared abstract or implement interface X

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

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