howto handle objects of private class, got as parameter - java

I learn Java at university and I have to do following excercise.
(simplified example)
import java.util.*;
public class A{
private static class B{
Integer b;
private B(int b){this.b = b;}
}
private static class B_Comparable extends B implements Comparable<B_Comparable> {
private B_Comparable(int b){super(b);}
#Override
public int compareTo(B_Comparable that) {
return this.b.compareTo(that.b);
}
}
private static class C<T> implements myList<T> { // see below
private ArrayList<T> lst = new ArrayList<>();
private static C<B_Comparable> createComparable() {
C<B_Comparable> ust = new C<B_Comparable>();
for (int i =0; i < 9; i++)
ust.lst.add(new B_Comparable(i));
return ust;
}
#Override
public T fetch(int index){
return lst.get(index);
}
}
private void test(){
C<B_Comparable> ustComparable = C.createComparable();
A result = ClassD.handle(ustComparable,3,4);
}
}
//--------------------------------------------------------
public class ClassD{
public static <T, S> T handle( S ustC, int pos1, int pos2 ){
// how can I compare elems of object ustC ?
ustC.fetch(pos1).compareTo(ustC.fetch(pos2));
//how can I fetch obj at pos1 ?
return ustC.fetch(pos1);
}
}
//-----------------------------------------
public interface myList<T> {
T fetch(int index);
}
static method handle gets an object (ustC) which is private. How can I
use methods, compareTo and fetch for this object? I have tried parametrisation, but if its the right way, I don't know how to solve.
Thanks for any help.

As discussed in comments, ustC, by virtue of the way handle is called in this context is of type C, which implements the myList interface. This interface exposes the fetch method, and is visible to your handle method.
The modification you arrived at in your comments would allow you to call fetch:
//Solution
public class ClassD {
public static <S extends Comparable> S handle(myList<S> ustC, int pos1, int pos2 ){
int y = ustC.fetch(pos1).compareTo(ustC.fetch(pos2));
return ustC.fetch(pos1);
}
}

Related

Java: builder pattern, inheritance and generics

I want to implement Builder Pattern with inheritance. So I have 4 following classes: one abstract class (ClassA), ClassB, ClassC. TestTest class is used to see how all this works:
public abstract class ClassA {
private String aString;
public String getaString() {
return aString;
}
public abstract class ClassABuilder<T extends ClassABuilder>{
public T setaString(String str) {
ClassA.this.aString = str;
return (T)this;
}
public abstract ClassA build();
}
}
public class ClassB extends ClassA{
private String bString;
public String getbString() {
return bString;
}
public class ClassBBuilder<T extends ClassBBuilder> extends ClassA.ClassABuilder<T>{
public T setbString(String str) {
ClassB.this.bString = str;
return (T)this;
}
#Override
public ClassB build(){
return ClassB.this;
}
}
}
public class ClassC extends ClassB{
private String cString;
public String getcString() {
return cString;
}
public static ClassCBuilder<ClassCBuilder> newBuilder(){
return new ClassC().new ClassCBuilder();
}
public class ClassCBuilder<T extends ClassCBuilder> extends ClassB.ClassBBuilder<T>{
public T setcString(String str) {
ClassC.this.cString = str;
return (T)this;
}
#Override
public ClassC build(){
return ClassC.this;
}
}
}
public class TestTest {
public static void main(String[] args) {
// TODO code application logic here
ClassC C=ClassC.newBuilder()
.setaString(null)
.setbString(null)
.setcString(null) //LINE XXX
.build();
}
}
The problem is that at TestTest at LINE XXX I get can't find symbol "setcString". What do I do wrong?
Let's track it down along the hierarchy:
First consider this signature:
class ClassABuilder<T extends ClassABuilder>
When you call setaString(null) the returned T will be an object that extends ClassABuilder. The compiler knows that this is a ClassBBuilder and thus will allow you to call setbString(null).
However, since the definition states T is required to extend a raw ClassBBuilder only any information on ClassBBuilder's generic types will be lost. Thus the compiler only knows that T is a ClassBBuilder but not that it's actually a ClassCBuilder which extends ClassBBuilder<ClassCBuilder> and hence doesn't know about setcString() on the returned type.
As has already been mentioned, using T extends ClassABuilder<T> will fix that since now the compiler knows there's another generic type to be passed down the hierarchy.
newBuilder() would then have to look like this:
public static ClassCBuilder<?> newBuilder(){
//you have too create a raw type here so you'll have to ignore/suppress/live with the warning
return (new ClassC().new ClassCBuilder());
}
As #AndyTurner already observed, the problem is that you use raw versions of your builder class types as type parameters. He did not go into detail, but the upshot is this:
ClassC C=ClassC.newBuilder() // yields a ClassCBuilder<ClassCBuilder>
.setaString(null) // yields a raw ClassCBuilder (type parameter)
.setbString(null) // yields a raw ClassBBuilder (type parameter bound)
.setcString(null) // ERROR: no such method on ClassBBuilder
.build();
To fix this with minimal change to your class structure and strategy, you must not only correct the type parameter bounds for your builder classes, as Andy advised ...
ClassABuilder<T extends ClassABuilder<T>>
... etc., but also make a change to ClassC.newBuilder(), such as to make it generic:
public static <T extends ClassCBuilder<T>> ClassCBuilder<T> newBuilder() {
return new ClassC().new ClassCBuilder<T>();
}
With that combination of changes, your code compiles for me.
I would like to post here the test demonstrating builder pattern with deep inheritance.
class TypeParamTest {
#Test
void test() {
Dd dd = Dd.builder()
.setIntAa(0)
.setIntBb(1)
.setIntCc(2)
.setIntDd(3)
.build();
assertEquals(0, dd.intAa);
assertEquals(1, dd.intBb);
assertEquals(2, dd.intCc);
assertEquals(3, dd.intDd);
}
abstract static class Aa {
int intAa;
static class AaBuilder<B extends AaBuilder> {
int intAa;
Aa build(Aa aa) {
aa.intAa = intAa;
return aa;
}
B setIntAa(int i) {
this.intAa = i;
return (B) this;
}
}
}
abstract static class Bb extends Aa {
int intBb;
static class BbBuilder<B extends BbBuilder<B>>
extends AaBuilder<B>
{
int intBb;
Bb build(Bb bb) {
bb = (Bb) super.build(bb);
bb.intBb = intBb;
return bb;
}
B setIntBb(int i) {
this.intBb = i;
return (B) this;
}
}
}
static class Cc extends Bb {
int intCc;
static CcBuilder<?> builder() {
return new CcBuilder<>();
}
static class CcBuilder<B extends CcBuilder<B>>
extends BbBuilder<B>
{
int intCc;
Cc build() {
return build(new Cc());
}
Cc build(Cc cc) {
cc = (Cc) super.build(cc);
cc.intCc = intCc;
return cc;
}
B setIntCc(int i) {
this.intCc = i;
return (B) this;
}
}
}
static class Dd extends Cc {
int intDd;
static DdBuilder<?> builder() {
return new DdBuilder<>();
}
static class DdBuilder<B extends DdBuilder<B>>
extends CcBuilder<B>
{
int intDd;
Dd build() {
return build(new Dd());
}
Dd build(Dd dd) {
dd = (Dd) super.build(dd);
dd.intDd = intDd;
return dd;
}
B setIntDd(int i) {
this.intDd = i;
return (B) this;
}
}
}
}

Why couldn't I deal with argument in java?

I'm java virgin. I've made really simple code like below.
class TreeData implements Comparable<TreeData> {
private String sixString;
private ArrayList<Integer> stringNum = new ArrayList<Integer>();
private ArrayList<Integer> charNum = new ArrayList<Integer>();
public TreeData(String sixString, int stringNum, int charNum){
this.sixString = sixString;
(this.stringNum).add(stringNum);
(this.charNum).add(charNum);
}
public int compareTo(TreeData other) {
return sixString.compareTo(other.getSixString());
}
public String getSixString(){
return sixString;
}
}
class Child<T extends Comparable<T>>{
public void print(T data){
//error : String a = data.getSixString();
System.out.println("hi");
}
}
public class Test {
public static void main(String[] args) {
Child<TreeData> child = new Child<TreeData>();
TreeData td = new TreeData("sixString", 8, 2);
child.print(td);
}
}
I had a problem in 'print' method in the Child class. When I tried calling the getSixString() method of data(passed as argument), it occurs error. I don't know why I can't using public method in the argument 'data'. Is it related with Generic? Thanks, in advance.
In your Child class, you only define T to be extending Comparable. Yet you expect it to have the method getSixString which Comparable doesn't have. What you probably want it for it to be extending TreeData:
class Child<T extends TreeData>{
public void print(T data){
String a = data.getSixString();
//should work now since T defines getSixString()
}
}
Or better yet if all you want is for T to be TreeData, you don't need any generic class. I'm assuming your real intention was:
class Child extends TreeData {
public void print(){
String a = getSixString();
}
}

Protected fields and generics

I have an abstract class MotorFahrzeug and an extending class LKW as shown below. I wrote a generic class with type parameter <T extends MotorFahrzeug> implementing a comparator. I'm wondering why the method compare( T m1, T m2 ) in this generic class has access to the protected fields. Can someone explain this, please?
package de.bauer;
public abstract class MotorFahrzeug {
protected int id;
protected int hubraum;
protected int leistung;
// some stuff
}
}
package de.bauer;
public class LKW extends MotorFahrzeug {
private String kategorie = "Nutzfahrzeug";
// Konstruktor
LKW(int i, int l, int h) {
// some stuff
}
// some stuff
}
package de.bauer;
import java.util.Comparator;
public class VergleichHubraum<T extends MotorFahrzeug> implements Comparator<T> {
#Override
public int compare(T m1, T m2) {
int retValue = -1;
if( m1.hubraum == m2.hubraum)
retValue = 0;
if( m1.hubraum > m2.hubraum)
retValue = 1;
return retValue;
}
}
With a declaration like
package de.bauer;
public class VergleichHubraum<T extends MotorFahrzeug> implements Comparator<T> {
The type T is guaranteed to be bound to a subtype of MotorFahrzeug. Since MotorFahrzeug is in the same package as the class declared above, you can access any of its protected members through a reference of type T.

Can a Constructor in a Class have more than 1 super()? (Java or GWT)

I have this class public class IndexedColumn extends Column<List<String>, String>. I want that class to super different objects depending on different key variable.
The following code is ok but it only have 1 super (new ClickableTextCell())
public class IndexedColumn extends Column<List<String>, String>{
private final int index;
public IndexedColumn(int index) {
super(new ClickableTextCell());
this.index = index;
}
#Override
public String getValue(List<String> object) {
return object.get(this.index);
}
public int getIndex(){
return index;
}
}
In other class
int myIndx=getIndex();
IndexedColumn nameColumn=null;
if(text.equals("clickText")){
nameColumn=new IndexedColumn(myIndx);
}
However, if i want to both super(new ClickableTextCell()) & super(new ButtonCell()) , then it got error
public class IndexedColumn extends Column<List<String>, String>{
private final int index;
public IndexedColumn(int index, int cellType) {
if(cellType==1)
super(new ClickableTextCell());
else{
super(new ButtonCell());
}
this.index = index;
}
}
So the eclipse suggested me to have another constructor like this:
public class IndexedColumn extends Column<List<String>, String>{
private final int index;
public IndexedColumn(int index) {
super(new ClickableTextCell());
this.index = index;
}
public IndexedColumn(int index, int forNothingKey) {
super(new ButtonCell());
this.index = index;
}
}
then in other class
int myIndx=getIndex();
IndexedColumn nameColumn=null;
if(text.equals("clickText")){
nameColumn=new IndexedColumn(myIndx);
}
else if(text.equals("clickButton")){
int forNoGoodReason=1;
nameColumn=new IndexedColumn(myIndx, forNoGoodReason);
}
As you can see, in order to be able to use ButtonCell column, i have to use an int forNoGoodReason variable for nothing.
Is it a good practice to do that?
or can you find a better way to fix it?
In Java, the superclass of a class is explicitly declared in the class header; e.g.
public class Foo extends Bar ... {
....
}
Every class apart from Object has exactly one superclass determined at compile time. It cannot be changed or selected dynamically / at runtime.
GWT, being based on Java and the Java type system has the same restriction.
On the other hand, you can declare a class with multiple constructors like this:
public class Bar ... {
public Bar (Integer i) { ... }
public Bar (Double d) { ... }
}
and do this:
public class Foo extends Bar ... {
public Foo (Integer i) {
super(i);
...
}
public Foo (Double d) {
super(d);
...
}
}
But, you cannot do anything like this:
public class Foo extends Bar ... {
public Foo (Integer i, Double d, boolean b) {
super(b ? i : d);
...
}
}
The problem is that the the super call in a constructor must resolve to a single constructor overload in the superclass at compile time, based on the static types of the arguments provided to the super call.
The only way to get something like this if you are going to use new to create objects is to have a unified constructor in the superclass that handles both / all cases; e.g.
public class Bar ... {
public Bar (Object o) {
if (o instanceof Integer) {
...
} else if (o instanceof Double) {
...
} // etcetera
}
}
... but that is exceedingly ugly, not to mention the fragility, and harmful coupling.
The other alternative is to use a factory method ... like this:
public class Foo extends Bar ... {
public Foo (Integer i) {
super(i);
...
}
public Foo (Double d) {
super(d);
...
}
public static Foo createFoo(Integer i, Double d, boolean b) {
return b ? new Foo(i) : new Foo(d);
}
}

Is it the right way to do what Im trying? Abstract static variable?

Look on the code below. It seems to be like there is easier way to do it.
For each new Class I want to add to the system, I have to do the following in order to set the class variable(static -> maxPlayers)?
Something like Abstract static variable?
protected abstract class Class{
protected abstract int getMaxPlayers();
public class Soldier extends Class{
public static final int maxPlayers = 4;
#Override
protected int getMaxPlayers() {
return Soldier.maxPlayers;
}
}
public class Demoman extends Class{
public static final int maxPlayers = 2;
#Override
protected int getMaxPlayers() {
return Demoman.maxPlayers;
}
}
public class Scout extends Class{
public static final int maxPlayers = 4;
#Override
protected int getMaxPlayers() {
return Scout.maxPlayers;
}
}
public class Medic extends Class{
public static final int maxPlayers = 2;
#Override
protected int getMaxPlayers() {
return Medic.maxPlayers;
}
}
}
its just like i have to repeat this template:
public static final int maxPlayers = 2;
#Override
protected int getMaxPlayers() {
return Medic.maxPlayers;
}
And i think it is not correct to do so.
First of all, you shouldn't name your class Class (not even for examples). Choose a better name.
Secondly, it seems like an enum is what you really need here:
public enum Army {
SOLDIER(4),
DEMOMAN(2),
SCOUT(4),
MEDIC(2);
private final int maxPlayers;
private Army(int maxPlayers) {
this.maxPlayers = maxPlayers;
}
public int getMaxPlayers() {
return maxPlayers;
}
}
No, you can't have an static variable in a base class that has a different value for each subclass (as far as I can tell, this is what you'd ideally want to do).
The way you did it is one option, another is using a non-static variable, as below.
And your variable should preferably have less scope than your getter function.
class Class
{
private final int maxPlayers;
Class(int max)
{
maxPlayers = max;
}
public int getMaxPlayers()
{
return maxPlayers;
}
}
class Soldier extends Class
{
Soldier()
{
super(4);
}
}
To increase readability and modifiability, you may want to consider replacing 4 here with an enum or similar.
Another way:
abstract class Class
{
public static int MAX_PLAYERS_SOLDIER = 4,
MAX_PLAYERS_DEMOMAN = 2,
...;
protected abstract int getMaxPlayers();
}
class Soldier extends Class
{
#Override
protected int getMaxPlayers()
{
return MAX_PLAYERS_SOLDIER;
}
}

Categories

Resources