Casting a class into another non hierarchical class form in java - java

Consider class A
class A {
int i;
int j;
int k;
}
and here is the class B
class B {
int a;
int b;
int c;
}
I was wondering if java has any such ting which allows to write/define our own custom casting logic.
For e.g.
to cast class B's object into class A's object where
i -> a // i pointing to value of a
j -> b // j pointing to value of b
k -> c // k pointing to value of c
(I can customize the logic to whatever i wish)
I have a few heavy weight objects to "cast" into some other classes to use and i do not want to write a converter method for this.
(casting operates only on the object in consideration and does not create another object)
any thoughts/suggestions for this ?
Thanks in Anticipation !

You can use the frameworks like ModelMapper (documentation) to define your maping logic and use it to convert object from one type to object of another type. E.g. this is how the configuration would be:
//Model Classes
class A{
int a;
}
class B{
int d;
}
//Mappings
PropertyMap<A, B> map = new PropertyMap<A, B>() {
protected void configure() {
map(source.a, destination.d);
}
};
//Test Program
public static void main(String[] args) throws Exception {
ModelMapper mapper = new ModelMapper();
PropertyMap<A, B> map = new PropertyMap<A, B>() {
protected void configure() {
map(source.a, destination.d);
}
};
mapper.addMappings(map);
A a = new A();
a.a = 10;
B b = mapper.map(a, B.class);
System.out.println(b.d);
}

This defeats the safety purposes of Java for two reasons.
Let's consider an updated version of your class code.
class A {
int i;
int j;
int k;
int l;
}
class B {
int a;
int b;
int c;
}
Now imagine what would happen if you did something like this, assuming the classes were written right above: (Warning:code will not compile)
public static void main(String[] args)
{
B classTwo = new B();
A classOne = (A) classTwo;
classOne.l = 3; // <-- what would happen?
}
As you can see, it won't work, because creating an instance of B will not allocate the variabls properly. This is why Java does not permit casting like that.
What Java does permit is converting between superclasses and subclasses.
For example:
class Fruit {
int i;
}
class Apple extends Fruit {
int j;
}
And now inside the main function:
Fruit f = new Fruit();
Apple a = (Apple)f; // this compiles, but will raise a ClassCastException
You'll ask, why does it raise a ClassCastException? Apple extends Fruit.
Yes, Apple extends Fruit. But, Fruit does not allocate memory for the j variable.
What is allowed is the other way around, casting an Apple to a Fruit, because all Apples have properties of Fruits (even in real life).
If you want to use your idea of casting, you could try an interface.
interface C {
public int getVarOne();
public int getVarTwo();
// NO variables here, only functions
}
Any class which implements (not extends) an interface must also implement all of the methods defined in it.
Once you've implemented the interface, the behavior is similar to casting to a superclass. There are also other uses for interfaces, but that is beyond the scope of this question.

No. There's no such thing as unions known from C. You cannot modify the memory directly in JVM. That's the point of Java. It sacrifices some potential for tricks, but in the end the code tends to be less buggy and easier to maintain than the code written in C.
If your concern is memory consumption caused by copying, you can convert A and B into interfaces. The interfaces should expose getters and setters. For example: int getI() and int getA(). Then you can introduce a class implementing both of them.
The indirection caused by the interface calls will have some performance cost, but in many cases, it won't be noticable.

Related

Mixing data in abstract class when working in parallel

I have a problem with my abstract class, I have an app for about 2000 users and many make calls at the same time to different classes, those classes share an abstract class
class A extends B{
//Code
}
The inconvenience arises when in my abstract class I receive parameters to some of my methods that in this case all classes call these methods.
class abstract B {
public int getResult(int b){
return b+1;
}
}
class C extends B {
public int getValue(int a){
int b = getResult(a);
int c = b * 2 / 4;
return c + 150;
}
}
When several people in parallel enter the class 'C' and pass different parameters to the method getResult ends up mixing the data sent and returns erroneous data in the execution.
The option that I have found is to implement the getResult method in each class, but that makes me repeat code in each class and there are about 200 classes that implement that abstract class
I've read that with encapsulation I can avoid that, but I don't know if that's the option since I haven't worked on it.
I have used the synchronized but it has created many bottlenecks and response times have increased.
I think you need use synchronized in your getValue method to manage parallel access to yout method. Maybe this article can help you, have a simple example too: https://dzone.com/articles/java-concurrency-synchronization#:~:text=the%20credit%20method
Note B class must have _"abstract" keyword before class.
Add "synchronized" in your getValue method
This way:
abstract class B {
public int getResult(int b){
return b+1;
}
}
class C extends B {
public synchronized int getValue(int a){
int b = getResult(a);
int c = b * 2 / 4;
return c + 150;
}
}

Avoid code duplication over classes

I am writing some classes and all of them implement a certain method they inherit from an interface. This method is close to the same for all the classes beside one call to a certain other function.
For example:
public void doSomething(){
int a = 6;
int b = 7;
int c = anOtherMethod(a,b);
while(c < 50){
c++;
}
}
What if multiple classes have the function doSomething() but the implementation of the method anOtherMethod() is different?
How do I avoid code duplication in this situation? (This is not my actual code but a simplified version that helps me describe what I mean a bit better.)
This looks like a good example of the template method pattern.
Put doSomething in a base class.
Declare abstract protected anotherMethod in that base class as well, but don't provide an implementation.
Each subclass then provides the proper implementation for anotherMethod.
This is how you could implement the technique that Thilo talked about in the following demo:
Main class:
public class Main extends Method {
public static void main(String[] args) {
Method m = new Main();
m.doSomething();
}
#Override
public int anOtherMethod(int a, int b) {
return a + b;
}
}
Abstact class:
public abstract class Method {
public abstract int anOtherMethod(int a, int b);
public void doSomething() {
int a = 6;
int b = 7;
int c = anOtherMethod(a, b);
System.out.println("Output: "+c);
}
}
This way, all you have to do is override anOtherMethod() in each class that you want to use doSomething() with a different implementation of the method anOtherMethod().
Assuming every version of anOtherFunction takes two integers and returns an integer, I would just have the method accept a function as an argument, making it Higher Order.
A function that takes two arguments of the same type and returns an object of the same type is known as a BinaryOperator. You can add a argument of that type to the method to pass a function in:
// Give the method an operator argument
public void doSomething(BinaryOperator<Integer> otherMethod) {
int a = 6;
int b = 7;
// Then use it here basically like before
// "apply" is needed to call the passed function
int c = otherMethod.apply(a,b);
while(c < 50)
c++;
}
}
How you use it though will depend on your use case. As a simple example using a lambda, you can now call it like:
doSomething((a, b) -> a + b);
Which simply returns the sum of a and b.
For your particular case though, you may find that having doSomething as part of a Interface isn't necessary or optimal. What if instead, anOtherMethod is what's required to be supplied? Instead of expecting your classes to supply a doSomething, have them supply a BinaryOperator<Integer>. Then, when you need to get results from doSomething, get the operator from the class, then pass it to doSomething. Something like:
public callDoSomething(HasOperator obj) {
// There may be a better way than having a "HasOperator" interface
// This is just an example though
BinaryOperator<Integer> f = obj.getOperator();
doSomething(f);
}

Class-specific method visibility

Is there some object oriented thing that you can call some methods from certain classes, but not all of them? Is there something like that which is similiar to protected?
Say you have a method void foo() and you want it to be available to the programmer in a few types of classes (perhaps something like using Type variables (to specify: T type). Now, perhaps is there some way, without inheriting the class with foo() in it, or making an interface, to specify which classes or types of classes have access to that method?
I would guess this could be like multiple-inheritance and polymorphism? But I still want only the class and certain classes to access the method without changing the visibility of the method. I want the visibility to be class-specific.
Here is an example:
class A sees foo() as private, but only that class sees it as private.
class B sees foo() as public/protected, but only that class sees it as public.
The method type would be default.
I guess what is easier to ask and answer to is: "Is there class-specific visibility?"
There is something like you are asking for in C++, it is called friend classes. Nevertheless, that concept is not supported by Java:
'Friends' equivalent for Java?
A second option is to use code reflection to access a class private members but it isn't such a clean solution and only works for protected elements:
public class C1 {
public C1()
{
x = "Hello Word!";
}
protected String x;
}
At a different class's method:
String val = (String)obj.getClass().getDeclaredField("x").get(obj);
System.out.println("val: " + val);
EDIT: After making a little bit of research I found it is possible even to access private members:
Field field = obj.getClass().getDeclaredField("x");
field.setAccessible(true);
String val = (String)field.get(obj);
field.setAccessible(false);
No, there's nothing like that in Java.
The closest you've got is putting classes within the same package, at which point they have access to any members which don't specify any access modifier. You can't specify particular classes though.
Another option which is appropriate in some cases is to use nested classes:
class Outer {
private static class Inner {
}
}
Here Outer and Inner have access to each other's private members.
Access Levels
Modifier Class Package Subclass World
public Y Y Y Y
protected Y Y Y N
no modifier Y Y N N
private Y N N N
thats your lot, there are not any other access modifiers.
With a little sleight of hand you can make one class seem to be two different classes:
// An interface.
interface A {
public void a ();
}
// Another interface.
interface B {
public void b ();
}
// Deliberately NOT stating we implement either A or B but actually we implement both.
class C {
public void a () {
}
public void b () {
}
}
// Pick either implementation from C and tell the world about it.
class D extends C implements A {
// Do nothing - already done by C.
}
class E extends C implements B {
// Do nothing - already done by C.
}
public void test() {
A d = new D();
B e = new E();
}
Here D and E are actually identically functioned objects because they are both actually Cs. However, as they are created they are made to seem to be A or B which are two different interfaces.
Unfortunately we cannot hide the fact that they both extend C but a little further sleight of hand and we can do that too with a Factory.
// Hide the guts of it all in a factory.
static class Factory {
// Make sure you MUST use the factory methods.
private Factory () {
}
// Construct an A.
public static A newA () {
return new D();
}
// Construct a B.
public static B newB () {
return new E();
}
}

assigning same values to objects in java

let's suppose there are two objects of class abc
abc obj = new abc(10,20); // setting the values of two var. say x and y
abc obj1 = obj; // pointing to same memory so same values
But if there is a way where I can assign the values of one object to another, both having diff. memory. Simply said I want the values to copied not the address. Any operator or something can do that ?
You can use the clone() method (assuming the subclass implements the java.lang.Cloneable interface)
abc obj1 = obj.clone()
Bear in mind the default behavior of clone() is to return a shallow copy of the object. This means that the values of all of the original object’s fields are copied to the fields of the new object(it will not go through the entire graph of other objects).
I you want to "deep-copy" the object you can serialize and deserialize it.
A deep copy makes a distinct copy of each of the object’s fields, recursing through the entire graph of other objects referenced by the object being copied
more info at:
http://javatechniques.com/blog/faster-deep-copies-of-java-objects/
In case of using clone() method you have to implement Cloneable interface and write your own implementation for this method. I think that better to create a copy constructor in your class and use it.
For example:
public class YourClass() {
private int prop1;
private int prop2;
...
// Getters and setters for properties.
...
// Default constructor
public YourClass() {
}
// Copy constructor
public YourClass(YourClass instance) {
this.prop1 = instance.getProp1();
this.prop2 = instance.getProp2();
// The same for other methods
}
}
Here is good post about clonning vs copy costructors vs factory methods on StackOverflow.
Try using 'operator overloading'.
I know, I know, Java doesn't have it, but that doesn't stop you from 'using' it.
All you need to do is:
obj1.copy(obj2);
And inside the declaration of abc
public void copy(abc other) {
var1 = other.var1;
var2 = other.var2;
}
I wish to stress, that this is merely from memory and untested, but I see no reason why it shouldn't work.
Alternative, you can use 'clone()', but be aware that 'references' within your class would get cloned over. Better to do it manually, really.
By overwriting 'copy', you can also make sure, that your subclasses are copied properly.
Use the clone method of Object class.
MyClass mobj = new MyClass("Vivek");
MyClass mobj1 = mobj.clone();
But for deep cloning try to use Serialization and Deserialization
Use deep cloning .Implement Cloneable Interface in class abc and implement clone()
abc obj = new abc(10,20); // setting the values of two var. say x and y
abc obj1 = obj.clone();
Cloning depends on your class structure .If you consider below simple class like your example.
class ABC implements Cloneable {
private int a;
private int b;
public int getA() {
return a;
}
public ABC(int a, int b) {
super();
this.a = a;
this.b = b;
}
public void setA(int a) {
this.a = a;
}
public int getB() {
return b;
}
public void setB(int b) {
this.b = b;
}
#Override
protected Object clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
return super.clone();
}
}
Test it in main will return false.
public static void main(String[] args) throws CloneNotSupportedException {
ABC a = new ABC(1, 2);
ABC b = (ABC) a.clone();
System.out.println(a == b);
}
You'll have to use clone method. The default behavior of clone is shallow copy.
You'll have to construct a new object.
As others point out, you can achieve this by implementing Cloneable and clone(), but you might as well might the new object explicit by implementing a Constructor or factory method that creates your new object out of the data held by the original.
The implementations won't differ much, yet I find the explicit instantiation less error prone to implement.
Josh Bloch comments on this in length in Effective Java. Depending on your edition, it is item 10 or item 11 in Chapter 3.

Correct use of co-variance in arrays

base class has a data-member which is an array of object A[] and an accessor method for that. I want to be able to over-ride the accessor to return a B[], where B is subclass of A.
In Java 5.0 on it will allow me to do that because arrays are co-variant, but I get a
ClassCastException when I try to something like the following:
class Business {
A[] clients;
A[] getClientList() { return clients; }
}
class DoctorBusiness extends Business {
B[] getClientList(){
return super.clients;
//this line thwoes a classcastexception
}
}
where Client corresponds to A and Patient corresponds to B and Patient extends Client.
How do I get round this ? I know that all the objects in the array are going to be of type B and would like to avoid having to cast down to Patient every-time I access array elements of clients
What about just
class A{}
class B extends A{}
public class Test<T extends A> {
T[] t;
public T[] get()
{
return t;
}
public static void main(String args[])
{
Test<B> t2 = new Test<B>();
B[] b = t2.get();
}
}
impossible.
you can use List<A>, cast it to List<B>, or have a generic List<T>. The performance should be very close to array.
See the comment I posted in your question. But if I am correct in understanding your question then the following applies:
A is not a sub type of B. That is why you are getting the exception. Based on what you are trying to do, it will not work.
I thought of a solution that will allow what you want. Enters the beautiful concept of the Interface!!! =D
public interface ICommon
{}
public class B extends A
{
protected B[] b;
public ICommon[] Get()
{
return b;
}
public ICommon[] GetAncestor()
{
return a;
}
}
public class A implements ICommon
{
protected A[] a;
public ICommon[] Get()
{
return a;
}
}
Now since they share a common interface. This will work as you wanted.
You will need to either expose methods that will allow you to use them by that type OR, you have to resort to casting when using them. That is the drawback
If you can change the super class, you might wish to retrofit it with generics as Steve B. suggests, or at least make the array creation overridable by the subclass:
class Super {
private A[] as;
protected A[] newDataArray(int length) {
return new A[length];
}
public A[] get() {
return as;
}
}
class Sub {
#Override protected B[] newDataArray(int length) {
return new B[length];
}
#Override public B[] get() {
return (B[]) super.get(); // we know it's a B[] because we created it
}
}
If you can't change the superclass, you can only do:
class Sub extends Super {
#Override public B[] get() {
A[] as = super.get();
return Arrays.copyOf(as, as.length, B[].class);
}
}
copyOf will fail with an ArrayStoreException should as contains something not assignable to B.
Covariance does not hold good for arrays and generics in Java because it kills static type safety. The only way to get around this design problem is to use separate lists in classes Business and DoctorBusiness.
Check out the "Arrays in C# and Java" section in this wikipedia page on Covariance
In boarding a plane you can upgrade/downgrade your class, but in Java or any usual object-oriented language you cannot downgrade a Fruit to be perceived as an Apple even though you can upgrade the view of an Apple as being viewed as a Fruit.
Fruit is a super class of apple and orange.
Fruit f;
Apple, Orange extend Fruit;
Apple a;
Orange b;
By common world sense, if you assigned f to apple,
f = apple;
you cannot return f as orange;
However,
If you had assigned a:
a = apple;
you would be able to return Fruit
Fruit get(){
return a;
}
You can return an apple as a Fruit, but not a Fruit as an apple, because what if f had been already assigned as an orange?
However, you may say, "Well B extends A is a one-to-one relationship, so I should have no worries about an instance of A being assigned to any other class other than a B." That is not how object-oriented language compilers see it. OO compilers do not have a relational model to enable it to inspect and restrict class extensions to 1-to-1.
Therefore, back to the question of OO principles. OO programming is an attitude. When you get your attitude right, you will not encounter such a dilemma because you would not even consider it.
Pardon me for saying this, that your encountering this issue signals that you are probably a visual basic ( or php or perl programmer) trying fit the linear programming attitude (as with all vb programmers) into the dimensionality of C# or Java. It is indeed frustrating both for the c#/java programmer and the vb programmer when both of them meet.
As an OO programmer, your visualization of the object hierarchy will spontaneously (some linguistically less discerning people would use the word "automatically") dictate your programming style. Just as your view of the fruit hierarchy would not even let you think of paying for apples when you actually have oranges in your cart.
Therefore, in the below example, you may set an instance of A to an instance of B and then return an instance of A.
But you cannot return an instance of A as an instance of B;
class A{}
class B extends A{}
public class Test {
A[] a;
B[] b;
public A[] get()
{
return a;
}
public void set(A[] a){
this.a = a;
}
// Illegal
public B[] getB(){
return a;
}
public static void main(String args[])
{
Test t2 = new Test();
B[] b = new B[0];
t2.set(b);
A[] a = t2.get();
}
}
If you do insist on returning B from an A instance, then both your concept of OO and your world view is broken.
Therefore, messr Cox's suggestion is correct. You have to use an interface as the contract declaration. You have to understand and have a spontaneous mental design of the program you are writing and the flow of contracts across your application. Just as you would have a spontaneous flow of contracts of fruit, vegetables, condiments, etc with the supermarket when you get your groceries.
You need to cease and desist attempting to get an instance B from its superclass instance A and redesign your attitude and mental process to spontaneously design your application that you need an interface.
interface Edible{};
class Fruit implements Edible{...}
class Apple extends Fruit {...}
Interface FoodAisle{
Edible get();
void set(Edible e)throws WrongFoodException;
}
class FruitSection implements FoodAisle{
Edible e;
public Edible get(){
}
}
class AppleBucket extends FruitSection{
Apple a;
public Apple get(){
return a;
}
public set(Edible e)
throws WrongFoodException{
if (!(e instanceof Apple)) throw WrongFoodException
e = e;
}
}
In designing a cross-food extension world view, you need to picture yourself as being able to ask the question - "what if they put a bunch oranges in the apple bucket in the fruit section?" Your worldview would jump up spontaneously to yell "I will make an exception complaint to the manager for misrepresenting oranges and being sold as apples". Similarly, whatever you are doing, if you persist in attempting to get a B from an A instance, it means you need to gain understanding of the business and processes for which you are programming, just as the manager need to have an understanding of food hierarchies.
It is imperative for programmers and data schema designers to have an expert knowledge of the processes and business for which they are programming.
You could also succumb to Steve B's suggestion of genericising your classes. If you choose to use generics, it means that
once you instantiate an aisle as for apples, you cannot attempt to get oranges from that aisle.
you are using generics because you wish to share routines among fruit buckets but you are not attempting the impossible miracle of turning oranges into apples.
.
class FruitSection<E extends Edible>{
E[] e;
public Edible get(){
}
void set(E e){
}
}
FruitSection<Fruit> fsect = new FruitSection<Fruit>();
Fruit[] ff = { .....};
fsect.set(ff);
AppleBucket<Apple> abuck = new FruitSection<Apple>();
Apple[] aa = { /* commalist of apples */};
abuck.set(aa);
placing apples into Fruit section is OK.
fsect.set(aa);
But placing any old Fruit in the apple bucket is not acceptable:
abuck.set(ff);
As usual, my typing too fast may yield some typos and misalignment. If so, pardon me.

Categories

Resources