java return abstract class in abstract method - java

I got some problem with java's interfaces and abstract classes.
I have interface
public interface IVector <T extends IVector>{
public IVector add(IVector vector);
public IVector sub(IVector vector);
public double dotProduct(IVector vector);
public IVector scalar(double scalar);
}
and abstract class like this:
public abstract class Vector implements IVector{
final ArrayList<Double> coordinates;
public Vector(ArrayList<Double> list){
coordinates = list;
}
public IVector add(Vector v){
ArrayList<Double> newCoordinates = new ArrayList<>();
if (v.coordinates.size() == this.coordinates.size()){
for (int i = 0; i < this.coordinates.size(); i++) {
newCoordinates.add(v.coordinates.get(i)+this.coordinates.get(i));
}
}
else return null;
return new IVector(newCoordinates);
}
Its just addition of vectors with n coordinates, how can i return result? I wanna use child classes (like 2dVector or 3dVector) in future?

You cannot create an abstract object directly - you need concrete class or override the required methods defined by the abstract.
Something like this may be what you are looking for.
public interface IVector<T extends IVector> {
public T add(T vector);
public T sub(T vector);
public double dotProduct(T vector);
public T scalar(double scalar);
}
public abstract class Vector<T extends Vector> implements IVector<T> {
final ArrayList<Double> coordinates;
public Vector(ArrayList<Double> list) {
coordinates = list;
}
}
public class AVector extends Vector<AVector> {
public AVector(ArrayList<Double> list) {
super(list);
}
#Override
public AVector add(AVector v) {
ArrayList<Double> newCoordinates = new ArrayList<>();
if (v.coordinates.size() == this.coordinates.size()) {
for (int i = 0; i < this.coordinates.size(); i++) {
newCoordinates.add(v.coordinates.get(i) + this.coordinates.get(i));
}
} else return null;
return new AVector(newCoordinates);
}
#Override
public AVector sub(AVector vector) {
return null;
}
#Override
public double dotProduct(AVector vector) {
return 0;
}
#Override
public AVector scalar(double scalar) {
return null;
}
}
Note that using public abstract class Vector implements IVector in your code introduces Raw Types and should be avoided. Notice I have used public abstract class Vector<T extends Vector> implements IVector<T> instead.
To achieve your aim of making the add method generic to all Vector objects as you seem to be trying to do you need some form of factory method.
Something like this may be a fair attempt at that.
public interface IVector<T extends IVector> {
public T add(T vector);
}
public interface Factory<T> {
public T makeNew (ArrayList<Double> coordinates);
}
public abstract class Vector<T extends Vector<T> & Factory<T>> implements IVector<T> {
final ArrayList<Double> coordinates;
public Vector(ArrayList<Double> list) {
coordinates = list;
}
#Override
public T add(T v) {
if (v.coordinates.size() == this.coordinates.size()) {
ArrayList<Double> newCoordinates = new ArrayList<>();
for (int i = 0; i < this.coordinates.size(); i++) {
newCoordinates.add(v.coordinates.get(i) + this.coordinates.get(i));
}
// Use the passed parameter as a factory.
return v.makeNew(coordinates);
}
return null;
}
}
public class AVector extends Vector<AVector> implements Factory<AVector> {
public AVector(ArrayList<Double> list) {
super(list);
}
#Override
public AVector makeNew(ArrayList<Double> coordinates) {
return new AVector(coordinates);
}
}

An abstract class cannot be instantiated: nor can an interface. You have to return either a subclass of Vector or an implementation of IVector.

Related

Restrain the type while inheriting

I created a java project to apply my GraphTheory course and enhance my java skills.
In this project :
I created a class Sommet<S>(Vertex in English) with an attribute Id with a generic type called <S>.
I created a class Arc<S>(Edge in English) with two attributes Sommet(Vertex).
I created a class EnsembleArc which is an HashSet of Arc
I also created a class ArcValue which inherit from Arc and have an int attribute Valeur(Value in English)
Here everything is fine and I dont have any problem.
But then I created a class EnsembleArcValue which inherit from EnsembleArc because every method from EnsembleArc will be useful to EnsembleArcValue.
But I also want EnsembleArcValue to be an HashSet of ArcValue (and I dont want an Arc which is not an ArcValue). And with the inheritance EnsembleArcValue is able to have an "simple" Arc in his Set.
So my question after all this explanation is :
Is there a way for EnsembleArcValue to inherit from EnsembleArc but will only accept an ArcValue in his Set.
Here is an image of The UML Project
I hope it will help to understand my problem (dont look at the bottom).
Here is the code :
public class Sommet<S>
{
//attributes
private S id;
public Sommet(S s)
{
setId(s);
}
public S getId()
{
return id;
}
public void setId(S s)
{
assert s!= null: "Objet null passé en paramètre";
id = s;
}
#SuppressWarnings("unchecked")
#Override
public boolean equals(Object obj)
{
boolean callback;
if(obj.getClass()!=getClass())
{
callback=false;
}
else
{
if(((Sommet<S>)obj).getId().equals(getId()))
{
callback=true;
}
else
{
callback=false;
}
}
return callback;
}
#Override
public int hashCode()
{
return getId().hashCode();
}
#Override
public String toString()
{
return getId().toString();
}
}
public class Arc<S>
{
private Sommet<S> depart;
private Sommet<S> arrivee;
public Arc(Sommet<S> dep, Sommet<S> arr)
{
setDepart(dep);
setArrivee(arr);
}
#Override
public String toString()
{
String str="("+getDepart().getId()+","+getArrivee().getId()+")";
return str;
}
public Sommet<S> getDepart()
{
return depart;
}
public Sommet<S> getArrivee()
{
return arrivee;
}
public void setDepart(Sommet<S> depart)
{
this.depart = depart;
}
public void setArrivee(Sommet<S> arrivee)
{
this.arrivee = arrivee;
}
#SuppressWarnings("unchecked")
#Override
public boolean equals(Object obj)
{
boolean callback;
if(obj.getClass()!=getClass())
{
callback=false;
}
else
{
if(((Arc<S>)obj).getDepart().equals(getDepart())&&((Arc<S>)obj).getArrivee().equals(getArrivee()))
{
callback=true;
}
else
{
callback=false;
}
}
return callback;
}
#Override
public int hashCode()
{
return getArrivee().hashCode()+getDepart().hashCode();
}
}
public class ArcValue<S,V> extends Arc<S>
{
private V valeur;
public ArcValue (Sommet<S> depart, Sommet<S> arrivee, V valeur)
{
super(arrivee,depart);
this.valeur=valeur;
}
public V getValeur()
{
return valeur;
}
}
import java.util.HashSet;
public class Ensemble<E> extends HashSet<E> implements Cloneable
{
private static final long serialVersionUID = -4354387895748449845L;
public Ensemble ()
{
super();
}
public Ensemble (Ensemble<E> ensemble)
{
for (E e : ensemble)
{
add(e);
}
}
public String toString()
{
StringBuffer str=new StringBuffer("{");
for(E e: this)
{
str=str.append(e.toString()+",");
}
str.setCharAt(str.length()-1, '}');
return str.toString();
}
#SuppressWarnings("unchecked")
#Override
public Ensemble<E> clone()
{
return (Ensemble<E>)super.clone();
}
}
public class EnsembleArc<S> extends Ensemble<Arc<S>>
{
public EnsembleArc(Ensemble<Arc<S>> ensemble)
{
super(ensemble);
}
public EnsembleArc()
{
super();
}
private static final long serialVersionUID = -4099925554493145279L;
public EnsembleSommet<S> listSucc(Sommet<S> sommet)
{
EnsembleSommet<S> XSucc=new EnsembleSommet<S>();
for (Arc<S> arc : this)
{
if (arc.getDepart()==sommet)
{
XSucc.add(arc.getArrivee());
}
}
return XSucc;
}
public EnsembleSommet<S> listPred(Sommet<S> sommet)
{
EnsembleSommet<S> XPred=new EnsembleSommet<S>();
for (Arc<S> arc : this)
{
if (arc.getArrivee()==sommet)
{
XPred.add(arc.getDepart());
}
}
return XPred;
}
public void add(Sommet<S> depart,Sommet<S>arrivee)
{
add(new Arc<S>(depart,arrivee));
}
#Override
public EnsembleArc<S> clone ()
{
return (EnsembleArc<S>)super.clone();
}
}
//import java.util.Collection;
public class EnsembleArcValues<S,V> extends EnsembleArc<S> //implements Collection<ArcValue<S,V>>
{
//TODO faire en sorte que ensembleArcValués ne contienne que des ArcsValue
private static final long serialVersionUID = -7163498825360866323L;
}
And you'll need this one to :
public class EnsembleSommet<S> extends Ensemble<Sommet<S>>
{
public EnsembleSommet()
{
super();
}
public EnsembleSommet(EnsembleSommet<S> ensemble)
{
super(ensemble);
}
private static final long serialVersionUID = 7278825382690341067L;
#Override
public EnsembleSommet<S> clone ()
{
return (EnsembleSommet<S>)super.clone();
}
public Sommet<S> firstSommet()
{
#SuppressWarnings("unchecked")
Sommet<S>[] tab=new Sommet[size()];
return toArray(tab)[0];
}
}
The only way you can achieve this is to make the type of Arc you want part of your generic deceleration. Rename your existing EnsembleArc to AbstractEnsembleArc and change it's generic decleration from < S > to < S, T extends Arc< S > > i.e.:
public abstract class AbstractEnsembleArc<S, T extends Arc<S>> extends Ensemble<T> {
// PUT ALL YOUR LOGIC CURRENTLY IN EnsembleArc HERE
}
Now create a new Class Called EnsembleArc and extend the new abstract class you've added, this new class will work identically to your existing EnsembleArc and class decleration should now look like:
public class EnsembleArc<S> extends AbstractEnsembleArc<S, Arc<S>> {
}
Finally have EnsembleArcValues extend the Abstract class instead of EnsembleArc so that you can declare that it should only accepts ArcValue and not simple Arc, do that like this:
public class EnsembleArcValues<S, V> extends AbstractEnsembleArc<S, ArcValue<S, V>> {
}

howto handle objects of private class, got as parameter

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

how to convert this ArrayListClass to abstract class

I am learning Java and don't understand why this code generates the following error: "ArrayListClass is abstract; cannot be instantiated. Help would be appreciated.
import java.util.*;
public class ArrayListClass {
protected Object[] list;
protected int maxSize;
protected int length;
public ArrayListClass() {
maxSize = 100;
length = 0;
list = new Object[maxSize];
}
public ArrayListClass(int size) {
maxSize = size;
list = new Object[maxSize];
length = 0;
}
public boolean isEmpty() {
return length == 0;
}
public boolean isFull() {
if (length == maxSize)
return true;
else
return false;
}
public int listSize() {
return length;
}
public int maxListSize(){
return maxSize;
}
public void print() {
System.out.print("The list contains:");
for(int i = 0; i < length; i++)
System.out.print(list[i] + " ");
System.out.println();
}
public boolean isItemAtEqual(int location, Object item) {
return (list[location].equals(item));
}
public void insertEnd(Object item) {
if(!isFull())
list[length++] = item;
}
public static void main(String [] args) {
ArrayListClass dac = new ArrayListClass(5);
dac.insertEnd(4);
dac.insertEnd(5);
dac.insertEnd(6);
dac.print();
System.out.println("dac.isItemAtEqual(0,9)"+dac.isItemAtEqual(0,9));
System.out.println("dac.isItemAtEqual(1,9)"+dac.isItemAtEqual(1,9));
}
}
You can not instantiate any abstract class in any programming language. Basic construct of abstract is, it is merely blueprint, not a real object. It provides the template of a class and will provide the form or outline of the class to the concrete classes that implement the class ('extend' the class...)
So you can not instantiate ArrayListClass, as this gives a blueprint. If you extend this class say DerievedArrayListClass extends ArrayListClass, then you will be able to instantiate DerievedArrayListClass .
package com;
abstract class ArrayListClass{
protected Object [] list;
protected int maxSize;
protected int length;
public ArrayListClass(){
maxSize = 100;
length = 0;
list = new Object [maxSize];
}
public ArrayListClass(int size){
maxSize=size;
list=new Object [maxSize];
length=0;
}
public boolean isEmpty(){
return length==0;
}
public boolean isFull(){
if(length==maxSize)
return true;
else
return false;
}
public int listSize(){
return length;
}
public int maxListSize(){
return maxSize;
}
abstract void print();
public boolean isItemAtEqual(int location, Object item)
{
return (list[location].equals(item));
}
public void insertEnd(Object item){
if(!isFull())
list[length++] = item;
}
}
public class ArrayListClassImpl extends ArrayListClass{
public ArrayListClassImpl(int i) {
super(i);
}
public void print(){
System.out.print("The list contains:");
for(int i = 0; i < length; i++)
System.out.print(list[i] + " ");
System.out.println();
}
public static void main(String [] args){
ArrayListClass dac = new ArrayListClassImpl(5);
dac.insertEnd(4);
dac.insertEnd(5);
dac.insertEnd(6);
dac.print();
System.out.println("dac.isItemAtEqual(0,9)"+dac.isItemAtEqual(0,9));
System.out.println("dac.isItemAtEqual(1,9)"+dac.isItemAtEqual(1,9));
}
}
Your code is fine . it is getting compiled and executed without any error on my eclipse and output is :
The list contains:4 5 6
dac.isItemAtEqual(0,9) false
dac.isItemAtEqual(1,9) false
If you convert the class to abstract, you must create a separate class that implements your abstract class.
The implementing class must override the unimplemented methods in the abstract class and can optionally override any or all of implemented methods in the abstract class
An abstract class can have a *mix of implemented and unimplemented methods. An interface class can only contain unimplemented methods.
You instantiate the class that implemenents the abstract class, but you can't instantiate the abstract class itself, because abstract classes, and interface classes are considered templates or blueprints that describe the form that the implementation must follow. It's like a recipe. You can't bake the recipe itself, you must bake the ingredients.
Working example of creating, implementing and instantiating an abstract Java class...
Shape.java: abstract class
public abstract class Shape { // Indicates this is an abstract class
protected static String shapeType = "generic shape";
abstract void draw(); // Implementing class *MUST* provide (due to 'abstract' keyword)
void logGreeting() { // Children can *optionally* override this implementation
System.out.println("I want to say hello");
}
void logDescription() { // Children can *optionally* override this implementation
System.out.println("This shape is a " + shapeType);
}
}
Circle.java: implementing class
public class Circle extends Shape { // Extends (e.g. implements) abstract class
public Circle() {
shapeType = "Circle";
}
public void logGreeting() { // Overrides implementation already in abstract class
System.out.println("This is my overridden greeting message");
}
public void draw() { // Provides implementation for *unimplemented* abstract method
// This is a NOP for example only (normally you'd put code here)
}
}
TestAbstract.java: instantiating class
public class TestAbstract extends Circle {
public static void main(String args[]) {
Circle circle = new Circle(); // instantiates implementing class
circle.logGreeting();
circle.logDescription();
circle.draw();
}
Compile the code:
javac Shape.java
javac Circle.java
javac TestAbstract.java
Execute the code:
java TestAbstract.java
Output:
This is my overridden greeting message
This shape is a Circle

How to create a collection of different types objects to use it with polymorphis

I have a problem with the different type of objects in a collection, in that case ArrayList, here there is an example:
public interface CustomObject {}
public class CustomObjectA implements CustomObjects {}
public class CustomObjectB implements CustomObjects {}
In the main I call myMethod:
ArrayList<CustomObject> list = new ArrayList<>();
for(int i=0; i < list.size(); i++) {
myMethod(list.get(i));
}
myMethod is defined with an overloading as written below:
public void myMethod(CustomObjectA a) { ... }
public void myMethod(CustomObjectB b) { ... }
There is a compile-error. How can I solve? What's the right way to it (Collections, generics, wildcard ?)
One way to work around this is the use of the visitor pattern, which allows you to attach functionality, without touching your domain objects
// A visitor, which can 'visit' all your types
interface CustomObjectVisitor {
void visitA(CustomObjectA a);
void visitB(CustomObjectB b);
}
// Make CustomObject a visitee
public interface CustomObject {
void accept(CustomObjectVisitor visitor);
}
// Implement the classes with the accept method
public class CustomObjectA implements CustomObject {
#Override public void accept(CustomObjectVisitor visitor) {
visitor.visitA(this);
}
}
public class CustomObjectB implements CustomObject {
#Override public void accept(CustomObjectVisitor visitor) {
visitor.visitB(this);
}
}
Now you can make your Main class a visitor like this:
public class Main implements CustomObjectVisitor {
public void methodThatDidntWorkBefore() {
ArrayList<CustomObject> list = new ArrayList<>();
for(CustomObject obj: list) {
obj.accept(this);
}
}
#Override public void visitA(CustomObjectA a) { ... }
#Override public void visitB(CustomObjectB b) { ... }
}
Check out WikiPedia too, it's really useful once you wrap your head around it.
With:
public interface CustomObject { void myMethod(); }
public class CustomObjectA implements CustomObjects {
#Override
public void myMethod() {...}
}
public class CustomObjectB implements CustomObjects {
#Override
public void myMethod() {...}
}
Then:
ArrayList<CustomObject> list = new ArrayList<>();
for(int i=0; i < list.size(); i++) {
list.get(i).myMethod(); // invoke dynamic
}
Which will execute the method corresponding to what the object's dynamic type is.
e.g. If get(i) returns an object with a dynamic type of CustomObjectA it will execute CustomObjectA::myMethod.
You could try something like this:
public class myMethodClass {
public static void main(String[] args) {
ArrayList<CustomObject> list = new ArrayList<>();
for(int i=0; i < list.size(); i++) {
myMethod(list.get(i));
}
}
public static void myMethod(CustomObject o){
if(o instanceof CustomObjectA) myMethod((CustomObjectA) o);
if(o instanceof CustomObjectB) myMethod((CustomObjectB) o);
}
public static void myMethod(CustomObjectA a) { }
public static void myMethod(CustomObjectB b) { }
}
interface CustomObject {}
class CustomObjectA implements CustomObject {}
class CustomObjectB implements CustomObject {}

How do I create an instance of an interface to use as an argument to another class' constructor?

I got to classes and an interface. There is one class that implements the interface but that same class uses objects of the interface.
public interface Function {
public double eval(double valueIndependentVariable);
}
public class PiecewiseFunction implements Function {
private Function left;
private Function right;
private double boundary;
public PiecewiseFunction(Function left, Function right, double boundary) {
this.left = this.left;
this.right = this.right;
this.boundary = this.boundary;
}
#Override
public double eval(double valueIndependentVariable) {
if (valueIndependentVariable < boundary) {
return left.eval(valueIndependentVariable);
} else {
return right.eval(valueIndependentVariable);
}
}
}
As you see there are two Function objects used but how do I create those if I want an instance of PiecewiseFunction?
public class Functie {
public static void main(String[] args){
// how do I declare foo and bar?
Function graad = new PiecewiseFunction(foo, bar, 33);
System.out.println(graad.eval(26));
}
}
You could use any other class that implements Function:
class Foo implements Function
{
private double boundary;
public Foo(double boundary)
{
this.boundary = boundary;
}
#Override
public double eval(double valueIndependentVariable)
{
// add implementation here
}
}
So your example could look like this:
public class Functie
{
public static void main(String[] args)
{
Function foo = new Foo(10.0);
Function bar = new Foo(12.0);
Function graad = new PiecewiseFunction(foo, bar, 33);
System.out.println(graad.eval(26));
}
}

Categories

Resources