Java setting the super extended class from the a passed in object - java

I have a class like this
public class User implements UserInterface, Parcelable
{
public User(int userID, String firstName, String lastName, String mobileNumber, Date dateAccountCreated)
{
this.userID = userID;
this.firstName = firstName;
this.lastName = lastName;
this.mobileNumber = mobileNumber;
this.dateAccountCreated = dateAccountCreated;
}
}
And I then have another class that extends into this:
public class Invitee extends User
{
private int eventDescision;
public Invitee(User u, int eventDescision)
{
super() = u;
this.eventDescision = eventDescision;
}
}
Obviously this line super() = u; does not work. However, how can I achieve the this functionality where I pass the User object the invitee recieves and set it as the extended object without having to create another constructor? I know I can just the object as a variable with a getter and setter, however, I like the way it flows without doing this as and invitee is always user.

User you receive in Invitee constructor is a real instance and you are creating another one. You can not assign one instance in a super constructor, you only can copy it, with a copy constructor.

It should rather be:
super(u.getUserID(),
u.getFirstName(),
u.getLastName(),
u.getMobileNumber(),
u.getDateAccountCreated());

You cannot automatically pass an instance of the base class to the base class' constructor call (super) in the child class' constructor.
What you might want to do is pass the base class' properties in the super call.
For instance is User properties are not private:
public Invitee(User u, int eventDescision) {
super(u.userID, u.firstName, u.lastName, u.mobileNumber, u.dateAccountCreated);
...

You can:
Use decorator design patter in Invitee
Define costructor User(User u)
as people manthioned before: use super() with all parameters
Remember that super is calling constructor of superclass, so you can't call constructor which is not defined.

Related

Why subclasses inherit private fields?

I'm creating a new class which is vehicle. I'm expecting the only protected variables inherit to subclasses. But when I try to create Constructor with IDE, it is also using superclasses private variables? -Which is private String vehicleName- I'm not clearly understanding this situation. Shouldn't I use auto Concstructor?
public class Vehicle {
protected int capacityOfPassengers;
protected String mapOfRoute;
private String vehicleName;
public Vehicle(int capacityOfPassengers, String mapOfRoute,
String vehicleName) {
this.capacityOfPassengers = capacityOfPassengers;
this.mapOfRoute = mapOfRoute;
this.vehicleName = vehicleName;
}
}
public class LandVehicle extends Vehicle {
private String brand;
private int priceModel;
public LandVehicle(int capacityOfPassengers, String mapOfRoute,
String vehicleName, String brand, int priceModel) {
super(capacityOfPassengers, mapOfRoute, vehicleName);
this.brand = brand;
this.priceModel = priceModel;
}
}
Generally, a class has a default constructor, taking no arguments, IF no constructor has been provided by you.
When you subclass Vehicle with your LandVehicle, your LandVehicle is a type of Vehicle. This means that it inherits methods and field from its superclass, even if they are private. For the class LandVehicle these members are just not visible, but they are still present - otherwise it couldn't function properly. The private keyword is an access modifier, that changes visibility to the caller.
As a result, to instantiate a LandVehicle, you also must provide the required attributes of its superclass Vehicle (since there is no default, no-arg constructor in Vehicle). In your example, a LandVehicle without a name (from Vehicle) wouldn't make sense, since a LandVehicle is a Vehicle, which requires a name.
You cannot access vehicleName from LandVehicle. You just pass some string parameter to super constructor, and the super constructor sets the vehicleName. For example, you can't initialize this field inside LandVehicle class as this.vehicleName = vehicleName.

Java subclass constructors not calling parent class constructor

I ran into a weird situation the other day. Here it is:
I had an abstract class and a child class extending it. The abstract class had a no parameter constructor to initialize a map, but that's it.
The sub-class didn't have any constructors that I explicitly wrote, and everything worked fine.
Then one day I added a custom constructor in the subclass with a bunch of parameters for a unit test. This broke my main program, however, because the map in its parent class was always null.
To solve it, I put another constructor in the subclass that was totally blank (no params or anything). This for some reason assured that the super class constructor would be called and no null pointer exception thrown. Why was that not getting called before and why is it working now?
Subclass:
public class BillToSite extends XWStoreRequestDataElement {
private String country;
private String state;
private String county;
private String city;
private String zip;
private String address;
public BillToSite() { } //WHY DOES THIS FIX IT???
//Only used for unit test.
public BillToSite(String address, String city, String state, String zip, String county, String country){
this.address = address;
this.city = city;
this.state = state;
this.zip = zip;
this.county = county;
this.country = country;
}
Abstract class:
public abstract class XWStoreRequestDataElement {
private Map<String, String> attributes;
public XWStoreRequestDataElement(){
attributes = new HashMap<>();
}
I cannot explain why you experience BillToSite instances with attributes=null. That contradicts the way Java works. But I can explain why you have to write the no-args constructor.
Necessity of explicit no-args constructor
I suppose that in your program BillToSite instances are created using new BillToSite(), either explicitly or by some framework... (otherwise the class wouldn't have any instances).
In the original BillToSite.java you had no explicit constructor, so the Java compiler created one for you, effectively identical to the one you asked about.
Introducing the 6-args constructor deactivated the compiler's auto-creation of the no-args constructor, and as your code relies on this constructor, it's clear to me that it couldn't work any longer. Normally, you should have got compile errors for the new BillToSite() calls. If you didn't get them, I'd guess that the instance creation happens in some hidden place using reflection.
So, when you wrote the explicit no-args constructor, you re-introduced the missing element that was no longer auto-generated.
Calling the super constructor
You never need to explicitly begin a constructor with super() (we may regard it bad style if you omit it, thus not making clear which superclass constructor is to be used). If you don't explicitly call a super(...) or this(...) constructor, the compiler effectively inserts super() at the very beginning. In this regard, some of the other answers are misleading.
So adding that line to your BillToSite(...) constructors can't change anything.
I'd recommend that you run your program under debugger control with a breakpoint on the BillToSite() constructor and watch the attributes field. I'm sure it will be initialized to an empty HashSet. If you later experience a null value, the problem must be in another part of your code.
Simply call super(); in public BillToSite(){}
For example:
public BillToSite(String address, String city, String state, String zip, String county, String country){
super();
this.address = address;
this.city = city;
this.state = state;
this.zip = zip;
this.county = county;
this.country = country;
}
By default, Java provides a no-args constructor that makes a call to super() for any class that doesn't have any explicitly defined constructors. However, when you explicitly define a constructor, Java doesn't do that so you have to call super() yourself.
So, when you didn't have that subclass constructor, Java handled the no-args constructor for you, but when you added that subclass constructor, Java stopped handling that so you had to do it yourself. Another solution would to just explicitly call super() in your original subclass constructor instead of having a separate no-args constructor for it since all you really need to do is call super() to initialize the map.

Why to override a superclass and call it again inside the function?

I am reading a code which is done something like this, and I want to understand why it is doing this:
public abstract class Class2 extends Class1 {
...
#Override
public ObjectType someFunction() {
ObjectType var = super.someFunction();
....
return var;
}
}
So the someFunction() method has been overwritten and the someFunction() of the parent is called again inside it.
Does it make sense to you? What would be the motivation for doing this?
If you don't want to duplicate the code for the entire overridden method, but you want to change the logic a little bit or if you want to add a little bit of code, then you can call the overridden method and provide additional code.
This prevents duplication of code and logic in subclasses that wish to override a method but retain some behavior.
As yshavit has indicated in a comment, calling the overridden method may be the only way to access data that is private in the superclass.
Pretty usefull when you want to use inheritance properly.
Just imagine that you have a class Person which is composed by a name and a surname and you want to specify the job, like Farmer.
class Person {
private String name;
private String surname;
//... Constructor
public String getInfos() {
return this.name + " " + this.surname;
}
}
class Farmer extends Person {
//... Constructor
#Override
public String getInfos() {
return super.getInfos() + " is a farmer.";
}
}
Person p1 = new Person("Name", "Surname");
System.out.println(p1.getInfos());
// Show "name surname"
Person p2 = new Farmer("Name", "Surname");
System.out.println(p2.getInfos());
// Show "name surname is a farmer."

Different constructor for subclass

I have an abstract superclass with a constructor of the form
public classname(String name, int amount)
and want to create a subclass of that abstract class that instead of taking a String as its first parameter takes an integer value that represents a given String name, so e.g. 0 stands for some String, 1 for another and so on.
When I try to write a constructor of the form subclass(int number, int amount) I get an error of the form "implicit super constructor is undefined. Must explicitly invoke another constructor."
Why is it not possible to create another, different constructor in the subclass?
Wrong question, you can write another constructor in the subclass, but as the super class has no default/no-argument constructor, you have to explicitely call the constructor of the super class you mentioned to ensure the invariance of the super class.
As mentioned by others in derived class you need to invoke constructor of its super class using super(arguments). Also this call must be first instruction in your constructor so you will probably face problem where you will need to determine value you want to place as name before calling constructor like
MyClass(int id, int amount){
super("???",amount);
}
here we don't know yet what value to use in place of "???". Unfortunately you can't use
MyClass(int id, int amount){
if (id==1) super("foo",amount);
else super("bar",amount);
}
One of possible solutions is to create separate method which will return correct name based on id and use it as super parameter like
MyClass(int id, int amount){
super(choseName(id),amount);
}
private static String choseName(int id){
if (id==1)
return "foo";
else
return "bar";
}
One solution is to use static factory methods. Consider this:
public abstract class Amount
{
protected static final List<String> IDENTIFIERS
= Arrays.asList("idfor0", "idfor1" /* etc */);
protected final String identifier;
protected final int amount;
public static Amount forIdentifierNumber(final int number, final int amount)
{
return new IdBasedAmount(IDENTIFIERS.get(number), amount);
}
protected Amount(final String identifier, final int amount)
{
this.identifier = identifier;
this.amount = amount;
}
}
Then, in the same package:
final class IdBasedAmount
extends Amount
{
IdBasedAccount(final String identifier, final int amount)
{
super(identifier, amount);
}
}
Call from code:
final Amount amount = Amount.forIdentifierNumber(0, 20100);
After that, it is only a matter of defining whatever methods are needed in the Amount class (either final or delegated to subclasses).
Of course, adapt to your code.
Edit: an example of static factory methods yielding classes with different internal state but the same behaviour: here. SchemaKey is abstract, acts as an "interface" and has static factory methods within itself to generate concrete classes.
You need to call super() in your subclass's constructor and hence explicitly call the super class's constructor.

Calling superclass from a subclass constructor in Java

I am trying to create a constructor that takes a field as a parameter, then puts it in a field that is stored in a superclass. Here is the code I am using
public crisps(String flavour, int quantity) {
this.flavour = super.getFlavour();
this.quantity = quantity;
}
In the superclass I have initialised the field with
private String flavour;
and I have an accessor method
public String getFlavour() {
return flavour;
}
I am getting an error "flavour has private access in the superclass", but I believe this shouldn't matter as I am calling the accessor method that returns it to the field?
What you should do:
Add a constructor to your super class:
public Superclass {
public SuperClass(String flavour) {
// super class constructor
this.flavour = flavour;
}
}
In the Crisps class:
public Crisps(String flavour, int quantity) {
super(flavour); // send flavour to the super class constructor
this.quantity = quantity;
}
Comments
Some comments to your question:
"In the superclass I have initialised the field with "
private String flavour;
This is not an initialization, it is a declaration. An initialization is when you set a value.
"I am getting an error " flavour has private access in the superclass" but I believe this shouldn't matter as I am calling the accessor method that returns it to the field?"
When you call a accessor (aka getter), it is ok - depends on the getter visibility.
The problem in you code is the:
this.flavour =
because flavour is not a field declared on Crisps class, but on the supper class, so you can't do a direct access like that. you should use my suggestion or declare a setter on the super class:
public void setFlavour(String flavour) {
this.flavour = flavour;
}
Then you can use it on the child class:
public Crisps(String flavour, int quantity) {
this.quantity = quantity;
super.setFlavour(flavour);
}
flavour is private. Although you're reading it from the public method, you're assigning it to a private field, and you likely didn't declare it in this class.
You could set flavour to protected in the parent class or define a setter for it
Ultimately your code doesn't really make sense though. Even if it did compile, it would be more or less: flavour = flavour. Perhaps you should rethink what you're trying to do a little bit
I think you may need a tighter grasp on Java and Object Oriented Programming.
http://docs.oracle.com/javase/tutorial/java/concepts/
You should start here.
public crisps(String flavour, int quantity)
{
super(flavour);
this.quantity = quantity;
}
This should work as see Docs
make
private String flavour;
public,otherwise your subclasses won't have access to this String.
Your superclass doesn't know about existence of any subclass. According to Java documentation, "private" makes any variable and method available within that class,where private variable or method was declared, no any class has access to it,even subclasses.
Once you chance your access modifier, you won't get any errors.

Categories