I've a concrete class A that implements an interface B.
B ref = new A();
Code :
public interface B{
public abstract String[] getWords();
}
public class A implements B {
private String[] words = new String[] {};
public void setWords(String[] words){
this.words = words;
}
public String[] getWords(){
return this.words;
}
}
In the interface B, I've only getter method but no setter method though the class A has it.
So when I do this : B ref = new A();, will this code work and how will I set words?
You won't be able to call setWords on ref if it is defined as B ref = ....
This is one of the cases where you need to use the exact type when declaring the variable (or use a cast):
A ref = new A();
Alternatively:
you could create an interface C that extends B and contains both methods and have A implement C.
you could provide a constructor in A that takes a String[] words argument to initialise your words field, and not provide a setter at all.
I would personally favour the latter option:
public class A implements B {
private final String[] words;
public A(String[] words) {
this.words = words;
}
public String[] getWords() {
return this.words;
}
}
So when I do this : B ref = new A();, will this code work...
Yes, it will.
...and how will I set words?
You won't be able to unless you:
make A's constructor take the list of words; or
add setWords() to B; or
keep a reference of type A to your object; or
downcast ref to A.
Of these, I would go with one of options 1-3. The last option is only included for completeness.
You have to cast back to the original type if the interface does expose it
if (ref instanceof A)
((A) ref).setWords(words);
else
// something else.
A better solution is to add the method to the interface.
B ref = new A();//1
ref.setWords(whatever);//2
The above code wouldn't compile as setWords() is not defined in your interface B, you'd get a compiler error on line 2.
as other have already expressed in their answers. you got 2 options as work arounds
Create object as A ref = A();
Downcast the ref to A type like ((A)ref).setWords(watever);
So when I do this : B ref = new A();, will this code work
Yes
and how will I set words?
You cannot. You need to have setter method in your interface.
Between you don't need to define method as abstract. It is by default abstract.
Related
I have 2 different classes with different fields and a class which has all the fields of both classes. Is there any way to cast the object in to two separate objects?
class A{
private int a;
private int b;
}
class B{
private int a;
private int b;
}
If object D have all the properties of A and B classes, Is there any way to cast them separately?
Casting take place from child to parent (downcast) or vise versa (upcast):
class A extends B
B b = (B)(new A());
or in case of interfaces:
List<String> myList = new ArrayList<>();
ArrayList<String> myArrayList = (ArrayList)myList;
Be careful when casting - if casting is not possible, you'll receive Exception!
In your case, mapping is what you're looking for. You simply need a mapper.
For example:
public class AToBMapper {
public static A fromB(B b) {
A a = new A();
a.setA(b.getA());
a.setB(b.getB());
return a;
}
public static B fromA(A a) {
//fill in
}
}
As complement of the very good answer of xenteros, you could also use library to do it if you have to repeat this task for many classes.
Spring, apache-commons and many others provides utility class to copy field by field which one of them that have the same name and type between two classes:
For example with ModelMapper :
ModelMapper mapper = new ModelMapper();
A a = new A(....);
B b = mapper.map(a, B.class)
Some libraries are very efficient (Selma, MapStruct, JMapper). Most of them generating the code at compile time
Others are less efficient.
You should so evaluate this point, the size of objects to map and the mapping frequency before generalizing the use of this kind of library.
I want to ask you how a single method can return different types of objects in java?
lets say we have a class "a". class a is parent class of classes "b" and "c".
lets say we have an array list defined as:
java.util.ArrayList<a> list;
so this list can contain objects of class a, class b and class c.
lets say we create one object of class b, and one object of class c, and we add them to list.
now, i want to create a method like this:
public ? get_element(boolean first)
{
if (first)
{
return list.get(0);
}
else
{
return list.get(1);
}
}
my problem is, that i do not know what to put at the place of "?" in this method.
if i put "a", so, "public a get_element", when element is returned it is always of type "a", no matter if element was originally of type "b" or "c" when it was added.
but i want that element returned is of type of element added.
so, if i add element of type "b" at index 0 of the list, and element of type "c" at index 1, i wish when i call get_element method, that if i provide parameter equal to "false", that returned element is of type "c", and if i provide true when i call it, that returned element is of type b.
of course, i can cast returned element to the type i wish. but this is just simple example i wrote, but i for real have much more complex situation. i have about 10 classes which all extend one class, and array list which can contain any of those 11 types of objects, and they can be arranged in any way, so i can not know what type of element is at which position, unless i create a code which will try to cast to all types, one by one until it finds the one to which it can cast.
but i want to know, is there some kind of more easy way to do so?
to simplify my question, i wrote this .java file:
public class test
{
public static class a{}
public static class b extends a{}
public static class c extends a{}
public static java.util.ArrayList<a> list = new java.util.ArrayList<a>(2);
static
{
b first_object = new b();
c second_object = new c();
list.add(first_object);
list.add(second_object);
b first_returned_object = get_element(true);
c second_returned_object = get_element(false);
}
public static ? get_element(boolean first)
{
if (first)
{
return list.get(0);
}
else
{
return list.get(1);
}
}
}
my problem is that i do not know what to put before "get_element" in get element method.
what should i put in order that i can save object of type b in "first_returned_object", and object of type c in "second_returned_object"?
of course, this is just example, i would not use these classes, because they are useless, but i wrote this to make my question as simple as possible.
my real classes where i have this kind of problem have 5000+ lines, so i could not include those here, so i wrote the simplest possible version which demonstrates my problem.
any suggestions?
thanx.
post scriptum:
to caps lock haters: your hate is bidirectional here. ;)
You can use Generics to some what make the return type dynamic.
Try this one:
public static <Type> Type get_element(int index)
{
String s = list.get(index).getClass().toString(); // returns "class class_name"
String[] split = s.split(" ");
Class<?> theClass = Class.forName(split[1]); // You need "class_name"
return (Type) theClass.cast(list.get(index));
}
or simply:
public static <Type> Type get_element(int index)
{
return (Type) list.get(index);
}
public class A {
private String superStr;
public String getSuperStr() {
return superStr;
}
public void setSuperStr(String superStr) {
this.superStr = superStr;
}
}
public class B extends A {
private String subStr;
public String getSubStr() {
return subStr;
}
public void setSubStr(String subStr) {
this.subStr = subStr;
}
}
And I expect result likes below
public static void main(String[] args) {
A a = fuc();
B b = new B();
b = (B) a;
b.setSubStr("subStr");
System.out.println(a.getSuperStr() + b.getSubStr());
}
private static A fuc() {
A a = new A();
a.setSuperStr("super");
return a;
}
but java.lang.ClassCastException is ocuured.
How can I cast this?
I want use subclass variable and super class variable.
thank you
How can I cast this?
You can't. You can only cast when the object in question has an "is a" relationship with the type. In your case, you have an A object (the one from fn), which is not a B. (All B objects are As, because B extends A, but not all A objects are Bs.)
Consider: Let's call B Bird and A Animal: A Bird is an Animal, but not all Animals are Birds. So we can treat all Birds as Animals, but we cannot treat all Animals as Birds. When you're using a variable of a given type to refer to an object, you're treating the object as being of that type (e.g., B b = (B)a tries to treat the Animal a as a Bird).
Side note: There's no point to the indicated part of the code:
B b = new B();
// ^^^^^^^^^^
b = (B) a;
Since the very next line assigns to b (well, it would if it would compile), there's no purpose served by doing new B() and assigning that to b just beforehand. (Unless the B constructor has side-effects, which is generally a Bad Idea™.)
Casting a particular object to another types does not magically convert it into an instance of that class (or at least not in Java); Therefore, the object referenced by variable a does not e.g. have the field subStr to use despite that the object referenced by b after executing B b = new B(); does.
The others have already explained why you can't do that. I'm here to give you a simple alternative. Your B class could have a constructor that had an A as argument and you would simply wrap that A so you could "transform" it to a B. Using that your code would look way more clean, it would actually work and you were following a good design pattern. For more information check the Decorator Pattern
I have a problem with an extended class.
This are the classes:
class A{
}
class B extends A{
}
Now the problem is that I have a method that returns A , something like this:
public A doSomthing(){
}
And now I try to do something like this:
public static void main(){
B b = new B();
b = doSomething();
}
But it doesn't seem to work. Is there any way to solve this problem?
The only thing I thought about is it to have something like this:
class B extends A{
public B(A a){
copy all the fields from A to B}
}
And then do:
A a = new A();
a = doSomthing();
B b = new B(a);
Is there a better option?
Fundamentally I think you've missed what the assignment operator does. This statement:
b = doSomething();
changes the value of b to whatever the doSomething() method returns. It doesn't depend on the existing value of b at all. So similarly, when you have:
A a = new A();
a = doSomthing();
... it would make more sense to write:
A a = doSomething();
Now if you need to create an instance of B based on an instance of A, then it may well make sense to write:
A a = doSomething();
B b = new B(a);
or just:
B b = new B(doSomething());
... but you need to understand when existing values are used and when they're not.
Usually I find that when I need to do something like that, it's actually better to use composition than inheritance anyway - that B should have a reference to an existing A rather than extending A. That's certainly something to consider, but without a concrete example we can't say for sure.
You instantiate your object b to be of Type B instead of A therefore polymorphism would not work when calling doSomthing
Change your object b to be of Type A
Java does not have multiple inheritance (c# example) to enforce method signatures. Instead it would make sense to
public static A doSomthing(){
A result = new A();
...
return result;
}
Then you can use:
A a = A.DoSomthing();
B b = (B)A.DoSomthing();
Let's say we have class A as a parent class, and class C that extends it.
class A
{
void m()
{
System.out.println("A.m");
}
}
class C extends A
{
#Override
void m()
{
System.out.println("C.m");
}
}
What's the difference between reference A a and C c when we use them to point to the same object type, for example A a = new C(); and C c = new C();?
From this question: Java inheritance vs. C# inheritance, it looks like that as a and c points to object type of C, and there seems no difference in using them.
I tested this code, and they all prints C.m.
class inherit {
void x(A a)
{
a.m();
}
public static void main(String[] args) {
System.out.println("hello");
A a = new C();
C c = new C();
a.m();
c.m();
new inherit().x(a);
new inherit().x(c);
}
}
That depends what the object is going to be used for.
If what you actually need is an object that has A's interface(i.e. A's type), it's strongly recommended to use A a = new C();. This way it makes it clear that you want an A interface, not a C implementation. Later when you change your mind, you can safely change it to A a = new Another_Subtype_Of_A(); without breaking other code.
This is especially true when A is an interface(In your case, A is a class). For example, if you just want a list, List list = new ArrayList(); is clearly better than ArrayList list = new ArrayList();. That's called "programming to interface, not implementation".
If you're creating an object that specifically needs C's interfaces(esp. those not present in A), you'd better choose C c = new C();. If you write A a = new C() instead, sooner or later you still have to cast the object to C(because A doesn't have all of your desired interfaces), so why bother?
It's not about the runtime type of the variable. You may only know you have a Vehicle object at compile time and based on user input, that may be a GarbageTruck or SportsCar.
GarbageTruck t;
...
t = new SportsCar(); //can't do this!
// so we do this:
Vehicle t;
if(user.isFast()) {
t = new SportsCar();
} else {
t = new GarbageTruck();
}
Java is all about Interfaces and Implementations.
An Interface is simply a set of public fields (methods & properties) the describe how users can interact with a class that implements the interface.
An Implementation is the code that actually makes those methods and properties do something. An Implementation can be a class that implements an interface, or it could be a subclass of some other implementation.
When you instantiate a class, you're writing code like:
Interface a = new Implementation();
Often times, we wrap the Interface and the Implementation all together... put another way, when we define a class, whether we're explicitly implementing an interface or not, we're defining an Interface with every public method we write.
Thus, it's the Interface that affects what methods we can call, but it's the Implementation that affects what happens when we call them.
firstly A is parent class and C is child class when you do A a = new A() then object of A is created and hold by A handle. When you do C c = new C() then object ofC is creating and C handle holds it.. But when you do A a = new C() then object ofC is created and Ahandle holds it. It means all the properties ofC is now been used. Although handle ofA is used by properties (instance) of C are used. This us polymorphism. Now it will used all the overloaded methods of C and not of A
Usages as an example
The difference come when you create a large project having methods created for child classes
Assume you have hello method
public void hello(C c) { }
In future you have another class B which extends A.. in that case you cannot use hello as its argument is of type C.. And imagine you have many classes as a child of A which need to use such method (then how many such methods you will create). Polymorphism is the rescue
You create hello with A as argument
public void hello (A x) { }
and now you can use same method for all the children of A..
A c = new C()
A b = new B()
Now all can use hello
this is the beauty of polymorphism