Home > Software design >  downcast to subclass and get subclass only fields
downcast to subclass and get subclass only fields

Time:08-06

I have classes similar to DataRequest & DataWithIdRequest. DataWithIdRequest gets passed into my controller method. I want to pass the subclass object ONLY to another class for processing. However, when I try to downcast to DataRequest the extra field is still showing. How can I accomplish this?

public class DataRequest {

    private String name;
    

    public String getName() {
        return name;
    }

    public void setFirstName(String name) {
        this.name = name;
    }
}


public class DataWithIdRequest extends DataRequest {

    private Integer id;

    public Integer getId() {
        return contractKey;
    }

    public void setContractKey(Integer id) {
        this.id = id;
    }
}
    //controller
    
        processData(request);
    }
    
    //domain class
    public Boolean processData(DataRequest request) {
    
        //request here has DataWithIdRequest field
        //but I only want the subclass
    }

CodePudding user response:

public Boolean processData(DataRequest request) {  }

Because in your method processData, request's type is DataRequest. You want it to be DataWithIdRequest.

public Boolean processData(DataWithIdRequestrequest request) {  }

CodePudding user response:

You can only offer a part of an API (application programmer's interface), by separating the code in an interface.

public interface Identified {
    Integer getId();
    public void setContractKey(Integer id);
}

public class DataWithIdRequest extends DataRequest implements Identified {

    private Integer id;

    @Override
    public Integer getId() {
        return contractKey;
    }

    @Override
    public void setContractKey(Integer id) {
        this.id = id;
    }
}

public Boolean processData(DataRequest request) {
    if (request instanceOf Identified identified) {
        identified.setContractKey(13);
    }
}

Or move the problem to the caller:

public Boolean processData(Identified request) {
    request.setContractKey(13);
}

By the way it more usual to use int, boolean, the primitive types.

CodePudding user response:

To hide the information completely, you need to create a new instance of DataRequest by DataWithIdRequest (that's why mapping library like mapstruct is useful), but not directly passing it.


Explanation:

This is how inheritance works, imagine a method takes a parameter of an interface or abstract class, by using instanceof inside the method we can check the object actual type and do something specific. e.g.

public void drawShape(Shape shape) {
  if (shape instanceof Circle) {
    Circle circle = (Circle) shape;
    // do sth
  } else if (shape instanceof Square) {
    // do sth else
  }
}

The above example is completely valid (although not a good programming style, that's another story).

The object inside the memory holds all the actual class details, passing it to a method doesn't change anything to the memory. The parameter (e.g. shape) is only another reference to the same memory location.

CodePudding user response:

Maybe I don't understand the question fully but: as you want I it's not possible since:

public class DataWithIdRequest extends DataRequest

means DataRequest is a subset of DataWithIdRequest, it's an intersection.

You unfortunately need to find an other way

  •  Tags:  
  • java
  • Related