I have the following abstract class:
public abstract class AbstractGroup {
private String name;
.
.
.
}
I have two empty classes that extend this abstract class:
public class GroupA extends AbstractGroup {
}
public class GroupB extends AbstractGroup {
}
Is there a way to cast the following without getting a ClassCastException:
(group is of type GroupA)
group = (GroupB)group;
I need this object instance to become GroupB.
It's not possible. You cannot cast classes horizontally but only vertically. GroupA is not the subtype of GroupB so the exception always will be raised.
No you cannot, because a GroupA is not an instance of GroupB.
How about:
public abstract class AbstractGroup {
public Enum Group { GroupA, GroupB; }
private String name;
private Group membership;
.
.
.
}
And then:
group.setMembership(GroupB);
No, you can't. You can cast up or down on Inheritance hierarchy.
What you are asking for is not called casting, but conversion. Both terms are covered by the umbrella term coercion. Java will not convert an object for you automatically and it couldn't even if it tried since this is generally an ill-defined problem. You must write your own code that will do the conversion -- either in the form of a conversion constructor, or some static conversion method, or maybe an instance method in the source object that returns the converted object.
No it isn't possible. But what you may like to do is add some constructor to the Groups to allow construction from a different implementation.
public class GroupA extends AbstractGroup {
public GroupA(AbstractGroup otherGroup) {
this.name = otherGroup.name;
}
}
However if you find yourself needing to do this then perhaps your design may be wrong.
Possible if you do something like:
GroupA groupAobj = new GroupA();
AbstractGroup abstractObj = (AbstractGroup) groupAobj;
GroupB groupBobj = (GroupB) abstractObj;
the code compiles and runs.
Related
I realize the title is kind of messy, but that's the best I could come up with.
Below is a minimal example of what I wish, but am currently failing to do.
public class ObjectA {}
public class ObjectB extends ObjectA {}
public interface HandlerInterface<T extends ObjectA> {
public T easyToOverride();
public List<T> hardToOverride();
}
public class HandlerA implements HandlerInterface<ObjectA> {
public ObjectA easyToOverride() {
return new ObjectA();
}
public List<ObjectA> hardToOverride() {
return new ArrayList<ObjectA>();
}
}
public class HandlerB extends HandlerA implements HandlerInterface<ObjectB> {
/*
This method ovverides its super method with ease since its return
type directly inherits from the super class's return type
*/
public ObjectB easyToOverride() {
return new ObjectB();
}
/*
This method is NOT accepted by the Java syntax since List<ObjectB>
does NOT directly inherit from List<ObjectA>
The method signature for hardToOverride() clashes with the signature
in the super class and is not overridden because the return types
don't obviously inherit each other
*/
public List<ObjectB> hardToOverride() {
return new ArrayList<ObjectB>();
}
}
Ignore that these classes should be in their own files and that I have not included their imports. I just put it like this to make it easier to read.
As you may have understood by the comments in the class HandlerB, the method hardToOverride() is not accepted (throw this code into your IDE and watch it scream).
I realise I could just return a List<Object> and type cast the contents of the returned List object to the type that I personally know the specific handler instance returns (ObjectA or ObjectB), but that would mean that anyone using these methods has to understand the inner workings of them, and I do not like that.
What I want is to be able to override the List<ObjectA> hardToOverride() method with a method List<ObjectB> hardToOverride() without losing the hard typing that these methods provide.
So my final question is:
Is there any way to keep all of these interfaces, inheritances and overrides without loosing the strong typing they provide in my example code?
If not, what is a better way to achieve a similar set of classes and interfaces that actually works?
Your code is accepted if you declare HandlerA with a new generic even if this is never used really:
public class HandlerA<T> implements HandlerInterface<ObjectA> {
//....
}
NOTE: This is to be considered just a workaround but as result your example code will work as you asked. Moreover, even if HandlerA declares a generic, you can anycase instantiate it also without brackets:
ObjectA objectA = new HandlerA();
I´ve got a question about inheritance/force certain value to an attribute in Java I am not sure about, even I spend a lot of time thinking about it. I will try to be as simple as possible.
So I´ve got an abstract class Foo, which has the Lombok annotation #Data:
#Data
public abstract class Foo{
private String id;
protected BoundType type;
public abstract void setBoundType(BoundType boundType);
}
Here is the enum BoundType:
public enum BoundType {
IN, OUT;
}
And I´ve got another two classes, InFoo and OutFoo that extend Foo. The boundType of InFoo should always be the enum type IN. On the other side, the boundType in OutFoo should always be the enum type OUT. For instance:
#Data
public class InFoo extends Foo{
public void setBoundType() {
//ALWAYS HAS TO BE BoundType.IN
}
}
How can I enforce this? Not sure how to design it. Thanks in advance.
Make sure the constructor sets the correct value for each subclass, and then make sure there's no setter, so that there's no way to alter the value.
Also, see this post Omitting one Setter/Getter in Lombok on how to omit the setter for the BoundType field.
The correct value should be set in the constructor of the subclasses:
public InFoo() {
boundType = BoundType.IN;
}
If it is necessary to use the setter pattern, you can perform a check, there:
public void setBoundType(BoundType boundType) {
if(boundType != BoundType.IN)
throw new IllegalArgumentException();
this.boundType = boundType; // This line is actually unnecessary
}
Java - Is it possible to extend all the subclasses of a class with a single class?
Let's explain it with an example, the actual code is quite more complex. I have an Animal class with its own class hierarchy. Let's say that it has two subclasses: Testarrosa and Viper.
public class Car {
public abstract String getManufacturer();
}
public class Testarossa extends Car{
public String getManufacturer(){
return "Ferrari";
}
}
public class Viper extends Car{
public String getManufacturer(){
return "Dodge";
}
}
I want to extend all the Car subclasses with a RegisteredCar subclass.
public class RegisteredCar extends Car {
private String plateNumber;
public RegisteredCar (String plateNumber){
this.plateNumber=plateNumber;
}
public String getPlateNumber() {
return plateNumber;
}
}
At some point, I should be able to create a new RegisteredCar of a specific subclass. Something like
RegisteredCar c = new RegisteredCar<Viper>("B-3956-AC");
And call the c.getManufacturer() to obtain "Dodge" and c.getPlateNumber() to obtain B-3956-AC. Obviously, I should still be able to create a Car c = new Viper();
That is an example. Having an attribute in Car with null value if not registered is not enough for what I need.
In short, no that is not possible. You have to unfortunately modify your object model.
For example, what about having a Registration class this way:
public interface Registration<C extends Car> {
C getCar();
String getPlateNumber();
}
This way you can extract the information relating to registration in a single class, while maintaining your Car models.
You can then do helper methods like:
Registration<Viper> registeredViper = createRegistration(new Viper(), "B-3956-AC");
As others have said, no thats not really possible and your example could be solved by changing your model
As an alternative to inheritance you could use another class to wrap a Car instance.
I would make Car an interface (though having RegisteredCar extend Car should work too) and then attempt something like the following pseudo code:
class RegisteredCar<T extends Car> implements Car {
private final T car
RegisteredCar(T car) {
this.car = car;
}
... methods for RegisteredCar
... methods from Car delegating to `this.car`
}
Please excuse the somewhat bad code, I don't have an IDE open, and I always mess up generics without an IDE to hand.
Another possible solution is to use AOP, though I don't know how in fashion that is these days as but what you are describing could be a cross cutting concern.
A final alternative might be to use a language that allows for Extensions, Traits, Protocol or some other type of 'mix in'
In java it is prohibited to extends more than 1 class.
You could build chain from classes to extends, for example.
To solve the problem of mutiple inheritance in Java → interface is used
You should avoid inheritance as much as possible. Use abstractions (interfaces) to make your code elegant and maintainable. Just google why extends is evil.
public interface Car{
String getManufacturer();
}
public interface Registerable{
boolean isRegistered();
void register(String plateNumber);
void getPlateNumber();
}
public class Viper implements Car, Registerable
{
//all methods
}
With Generic class approach as described in other answer, you will not be able to use RegisteredCar where your require to pass Car object. e.g. suppose you need to generate some invoice.
Invoice getInvoice(Car c);
In this method you cannot use RegisteredCar as it is not of Type Car. All you API which require Car are not applicable to RegisteredCar. In some cases you may need Plate Number as well as Car, There you may need to keep mapping of Plate Number and Cars. I would suggest following approach based on Decorate Pattern and delegate all Car calls to passed car object
public class RegisteredCar extends Car{
public RegisteredCar(Car c, String plateNumber){
}
#Override
String getColor(){
c.getColor();
}
}
No, it's not like C++. Multiple inheritance is not possible in Java. However you can implement multiple interfaces.
You cannot achieve that with inheritance.
Your best option is making the RegisteredCar type generic, then having a generic instance variable that holds the intended type car:
public class RegisteredCar<T extends Car> {
private String plateNumber;
private T car;
public T getCar() {
return this.car;
}
public T setCar(T car) {
this.car = car;
}
public RegisteredCar (String plateNumber){
this.plateNumber=plateNumber;
}
public String getPlateNumber() {
return plateNumber;
}
}
With this, you will be able to pass into RegisteredCar an object of any type that's a subclass of Car.
As you can notice, I have removed the extends Car part of this class, as it doesn't need to be a subclass of car itself.
Is there a reason, in the real classes, that you couldn't simply add the new feature to the existing base class?
public abstract class Car
{
public abstract String getManufacturer() ;
protected String plate_number = null ;
public String getPlateNumber()
{ return this.plate_number ; }
public boolean isRegistered()
{ return ( this.plate_number != null ) ; }
}
A question about inheritance in java...
class Base {
private int val = 10;
}
class Derive extends Base{
public void setVal(int value) {
super.val = value;
}
}
Since we can change the private field in super class using super keyword in the subclass, why should we use protected to declare fields in super class?
You can't do that. The code you've given doesn't compile, unless Derive is declared as a nested class within Base (which is a pretty rare case).
You should be getting an error like this:
error: val has private access in Base
Check your code you can never access private out side the class even if you have inherited that class.
super is an reference variable which is used to call parents constructor.
Is there a way to force classes in Java to have public static final field (through interface or abstract class)? Or at least just a public field?
I need to make sure somehow that a group of classes have
public static final String TYPE = "...";
in them.
No, you can't.
You can only force them to have a non-static getter method, which would return the appropriate value for each subclass:
public abstract String getType();
If you need to map each subclass of something to a value, without the need to instantiate it, you can create a public static Map<Class<?>, String> types; somewhere, populate it statically with all the classes and their types, and obtain the type by calling TypesHolder.types.get(SomeClass.class)
You can define an interface like this:
interface X {
public static final String TYPE = "...";
}
and you can make classes implement that interface which will then have that field with the same value declared in the interface. Note that this practice is called the Constant interface anti-pattern.
If you want classes to have different values then you can define a function in the interface like this:
interface X {
public String getType();
}
and implementing classes will have to implement the function which can return different values as needed.
Note: This works similarly with abstract classes as well.
There is no way to have the compiler enforce this but I would look into creating a custom FindBugs or CheckStyle rule which could check for this.
I don't think it's possible. But you could make an interface with a getType method
Or at least just a public field?
That's IMO the usual way to go: In the superclass, require a value in the constructor:
public abstract class MyAbstract {
private final String type;
protected MyAbstract(String type) {
this.type = type;
}
public String getType() {
return type;
}
}
This way, all implementations must call that super-constructor - and they don't have to implement getType() each.
Implement an interface in your classes and call a method from that interface, like others have suggested.
If you must absolutely have a static field, you could make an unit-test that will go through the classes and checks with Reflection API that every class has that public static final field. Fail the build if that is not the case.