I have a class component
abstract class Component{
private componentType m_type;
public Component(componentType type)
{
m_type = type;
}
}
and 2 subclasses
class AmplifierComponent extends Component{
public AmplifierComponent()
{
super(componentType.Amp);
System.out.print(this.m_type);
}
}
class AttenuatorComponent extends Component{
public AttenuatorComponent()
{
super(componentType.Att);
System.out.print(this.m_type);
}
}
my problems are:
1.i can't instantiate any kind of component because m_type isn't visible(what that means?)
2.i need to make an array of all the components the user has insert to the chain. i can't manage to create an array of Component class.
can someone help me with the design?
or with some workarounds?
Thanks in advance
I don't understand why you need the type member. This looks redundant. You can instead simply do:
abstract class Component{
}
class AttenuatorComponent extends Component{
public AttenuatorComponent() {
// calls the default super constructor
}
}
and rely on polymorphism for your classes to behave appropriately. Having a type member to identify a hierarchy type is unnecessary when you've declared the corresponding classes. If you do have a member variable that is required to be visible in subclasses but not by clients, then you can make it protected rather than private.
Component could be an interface if there's no functionality/data associated with it.
Your array declaration would look like
Component[] components = new Component[20];
components[0] = new AttenuatorComponent();
Polymorphism would mean that you can iterate through this array of components, calling appropriate methods declared on (but not necessarily implemented by) the Component, and the suitable subclass methods would be called.
Set m_type to protected to be able to see it from child classes.
abstract class Component {
private componentType m_type;
public Component(componentType type)
{
m_type = type;
}
public componentType getType()
{
return this.m_type;
}
}
class AmplifierComponent extends Component{
public AmplifierComponent()
{
super(componentType.Amp);
System.out.print(super.getType());
}
}
class AttenuatorComponent extends Component{
public AttenuatorComponent()
{
super(componentType.Att);
System.out.print(super.getType());
}
}
That way you can read m_type, but cannot change it.
You could also make the getType() command protected, so it is only reachable through the classes which inherit it.
Related
I have an extending class which needs to use and extended version of a variable in the parent class. So far I've been getting away with using it like this:
public class ParentClass
{
protected ParentVariable variable;
public ParentClass(){
this.variable = new ParentVariable();
}
....
}
public class ChildClass extends ParentClass
{
public ChildClass(){
super();
this.variable = new ChildVariable();
//Where ChildVariable Extends ParentVariable
....
}
}
This more or less works so long as every time I use variable I cast it to ChildVarible but this is ugly and throws up some issues. Is there a better way to perform this? Thanks.
If it's possible to make your superclass abstract, you could solve this by using generics:
public abstract class ParentClass<T extends ParentVariable>
{
private T variable;
protected T getVariable(){
return variable
}
protected void setVariable(T variable){
this.variable = variable;
}
....
}
public class ChildClass extends ParentClass<ChildVariable>
{
public ChildClass() {
setVariable(new ChildVariable());
//Where ChildVariable Extends ParentVariable
ChildVariable foo = getVariable() // no cast nessecary
}
}
Notice that I made your field private. You should always access field by getter and setter methods, even in subclasses.
If this is not possible (maybe even if it was) it is an indicator that your design is flawed. Refactoring of all for classes might be needed to achieve a clean architecture. Unfortunately this depends on the whole implementation of all four classes and possibly the whole context those classes are used in. An answer to that would be too broad for stackexchange.
I have basically two types of each entity in my project which are distinguisched only by specifying the parent catalog type in the class generics declaration. Catalogs iteself are declared with generics as they can have links to a specific old catalog of the same type.
abstract class AbstractCatalog<T extends AbstractCatalog<T>> {
public abstract T getOld();
}
class Catalog1 extends AbstractCatalog<Catalog1> {
#Override
public Catalog1 getOld() { ... }
}
class Catalog2 extends AbstractCatalog<Catalog2> {
#Override
public Catalog2 getOld() { ... }
}
So far so good but the problem is that it becomes really cumbersome if I add some entities that must contain a link to a catalog of a certain type.
For instance,
abstract class AbstractCatalogHistory<C extends AbstractCatalog<C>, E extends AbstractHistoryEntry<C, E>> {
public abstract Set<E> getEntries();
}
abstract class AbstractHistoryEntry<C extends AbstractCatalog<C>, E AbstractHistoryEntry<C, E>> {
public abstract E getPrior();
}
class Cat1HistoryEntry extends AbstractHistoryEntry<Catalog1, Cat1HistoryEntry> {
#Override
public Cat1HistoryEntry getPrior() { ... }
}
class Cat2HistoryEntry extends AbstractHistoryEntry<Catalog2, Cat2HistoryEntry> {
#Override
public Cat2HistoryEntry getPrior() { ... }
}
class Catalog1History extends AbstractCatalogHistory<Catalog1, Cat1HistoryEntry> {
#Override
public Set<Cat1HistoryEntry> getEntries() { ... }
}
class Catalog2History extends AbstractCatalogHistory<Catalog2, Cat2HistoryEntry> {
#Override
public Set<Cat2HistoryEntry> getEntries() { ... }
}
so it gets much more difficult to get idea of what's going on while looking at such a hierarchy. This example is by no means complete and I have dozens of types that should be nested within those I provided above.
What I'm trying to do by doing this is to take advantage of type safe code which can be verified at compile time. But at the same time such a code becomes completely messy as I have to specify longer generics chains while adding new types to the hierarchy.
Is there a way to handle such generics explosion?
Your example doesn't make it entirely clear why you need to have separate classes for Catalog1 and Catalog2, but let's assume this is set.
However, even so I see no reason why everything else referencing these catalogs would require this kind of duplication. If you just want to make sure it's associated with the right catalog type, then this is the only generic parameter you should really need:
class CatalogHistory<C extends AbstractCatalog<C>> {
public Set<HistoryEntry<C>> getEntries();
}
class HistoryEntry<C extends AbstractCatalog<C>> {
public HistoryEntry<C> getPrior();
}
But what if you are actually doing different things in e.g. Cat1HistoryEntry and Cat2HistoryEntry so you need the separate classes? In that case you can obviously not get around having the abstract base class and two concrete implementations, but I see no need to introduce generic types and then nail them down to the concrete types the way you do:
abstract class AbstractHistoryEntry<C extends AbstractCatalog<C>> {
public abstract AbstractHistoryEntry<C> getPrior();
}
class Cat1HistoryEntry extends AbstractHistoryEntry<Catalog1> {
#Override
public Cat1HistoryEntry getPrior() { ... }
}
class Cat2HistoryEntry extends AbstractHistoryEntry<Catalog2> {
#Override
public Cat2HistoryEntry getPrior() { ... }
}
There are a few things going on here. First, consider AbstractHistoryEntry. If you have one of those, you are working on a generic level and should not care that getPrior returns this or that concrete subtype - all you need to know is that it returns another AbstractHistoryEntry object referencing the same catalog.
If you have a concrete Cat1HistoryEntry reference however, you can still get the full type safety of getting another Cat1HistoryEntry out of getPrior thanks to the covariance of return types in Java.
Now it gets slightly more complicated - Let's try to pull the same trick with AbstractCatalogHistory:
abstract class AbstractCatalogHistory<C extends AbstractCatalog<C>> {
public abstract Set<? extends AbstractHistoryEntry<C>> getEntries();
}
class Catalog1History extends AbstractCatalogHistory<Catalog1> {
#Override
public Set<Cat1HistoryEntry> getEntries() { ... }
}
class Catalog2History extends AbstractCatalogHistory<Catalog2> {
#Override
public Set<Cat2HistoryEntry> getEntries() { ... }
}
As you can see, both concrete subclasses still return a set of the concrete types Cat1HistoryEntry and Cat2HistoryEntry. The abstract base type now needs to express a common supertype for those sets so that you can work with the result in a generic way. This is done by introducing covariance.
Setters
Setters complicate the matter a bit. Basically, if you have a generic container / collection like a List<T> or an AbstractCatalogHistory<C>, and you want to allow both adding and retrieving items, you can no longer have variance in the item type if you want type safety.
For example, if you had a setter in AbstractCatalogHistory<C> which allows you to add any AbstractHistoryEntry<C> items to the history, then you have a problem, because if your AbstractCatalogHistory<C> is actually a Catalog1History then you only want Cat1HistoryEntry items in there!
This is the same problem as with generic lists: A List<Cat> is not a List<Mammal> because you can add an elephant to a List<Mammal>, but you shouldn't be able to add an elephant to a List<Cat>.
If you insist that a history for Catalog1 must consist only of Cat1HistoryEntry items, then a solution would be to only add a setter to Catalog1History, and none to AbstractCatalogHistory<C>. That way the generic classes would only be used for reading the history, not writing it.
However, going back to the beginning of my answer: If you don't actually don't need the dual concrete classes, the solution remains very simple. Unfortunately you still didn't explain why or if you need those. If all you really want is the Catalog1 / Catalog2 distinction, and you don't actually need a different implementation for e.g. Cat1HistoryEntry and Cat2HistoryEntry, then the following should suffice:
class CatalogHistory<C extends AbstractCatalog<C>> {
public Set<HistoryEntry<C>> getEntries();
public void addEntry(HistoryEntry<C> entry);
}
class HistoryEntry<C extends AbstractCatalog<C>> {
public HistoryEntry<C> getPrior();
public void setPrior(HistoryEntry<C> prior);
}
So I'm having trouble wrapping my head around the proper design for this.
My application has two key objects that control state, that need to interact with one another: ItemList, ItemState. These each rely on a generic ITEM_TYPE so they can function in different contexts. They are also abstract to allow for ITEM_TYPE-dependent behavior.
Both pieces need to know the generic type, but moreover, since they talk to one another, they need to know the generic types of one another. (An ItemList< String > instance needs to know that its ItemState field is an ItemState< String > and vice versa).
My current solution works, but it seems awful. There has to be a better way. This is what I'm doing now:
public abstract class ItemState<
ITEM_TYPE,
STATE_TYPE extends ItemState<ITEM_TYPE, STATE_TYPE, LIST_TYPE>,
LIST_TYPE extends ItemList<ITEM_TYPE, STATE_TYPE, LIST_TYPE>> {
}
public abstract class ItemList<
ITEM_TYPE,
STATE_TYPE extends ItemState<ITEM_TYPE, STATE_TYPE, LIST_TYPE>,
LIST_TYPE extends ItemList<ITEM_TYPE, STATE_TYPE, LIST_TYPE>> {
}
Then an implementing class might look like:
class StringState extends ItemState<String, StringState, StringList> {
}
class StringList extends ItemList<String, StringState, StringList> {
}
Note that for ItemState, STATE_TYPE is a reference back to the implementing class, and likewise for ItemList/LIST_TYPE.
Really my problem would be solved if I just make ItemState an inner class of ItemList since there would be an implicit binding and they could share generic declarations, but both classes are so large and standalone, that I would prefer not to do this.
Any suggestions?
Edit: As a counter-example to a comment:
public abstract class ItemState<ITEM_TYPE> {
public abstract ItemList getItemList();
public void doSomething() {
// This should not compile because abstract super class has
// no idea what the generic type of getItemList() is
ITEM_TYPE item = this.getItemList.getItem();
}
}
Edit 2: I think the best solution I could think of was just to make ItemList/ItemState inherit one way or the other so they can function as the same class. I don't love this solution because it overrides separation of concerns, but it makes the generics a lot more manageable.
Sidenote: my actual applicaiton had this problem with 4 intertwined classes, I just used 2 for simplicity. In actuality the generics were so bad they were incomprehensible and hard to refactor (about 4 entire lines of just generic declarations for each class). I've now made these 4 classes into a vertical inheritance hierarchy
JM Yang's solution is pretty good
I think you may just reference to generic type ITEM_TYPE when declaring these 2 classes.
I'm able to compile below code with no errors.
public abstract class ItemList<ITEM_TYPE> {
public abstract ItemState<ITEM_TYPE> getState();
public abstract ITEM_TYPE getItem();
}
public abstract class ItemState<ITEM_TYPE> {
public abstract ItemList<ITEM_TYPE> getItemList();
public void doSomething() {
ITEM_TYPE item = getItemList().getItem();
System.out.println(item);
}
}
public class StringList extends ItemList<String> {
#Override
public StringState getState() {
return new StringState();
}
#Override
public String getItem() {
return "";
}
}
public class StringState extends ItemState<String> {
#Override
public StringList getItemList() {
return new StringList();
}
}
I've to create a simple self-made ActiveRecord class for my project.
Only stuck on the problem that I have a getModel() in my Player class, which is being extended by a ActiveRecord class.
When I want to use the getModel() method from my ActiveRecord class, I cant use it cause it's not the same type. I don't want to reference Player here, because I want to use multiple models.
Anyone has a solution?
Ok so I got something up:
abstract class ActiveRecord<T> {
private T model;
public T getModel() {
return this.model;
}
}
public class Player extends ActiveRecord<Player> {
}
public class Event extends ActiveRecord<Event> {
}
But when I try to output this.model in my ActiveRecord class, it return null.
What is wrong here?
Your method definition needs to do something like this
public Class<? extends ActiveRecord> getModel();
Meaning of this is that the return type is of class that extends ActiveRecord. When you do this to the child it would return Player.class as Player extends ActiveRecord.
A brief note if getModel return an object of that class then you should remove Class from the method function
public <? extends ActiveRecord> getModel();
So if I understand well you have a super class called ActiveRecord and a subclass Player, which has a method getModel.
If you want to use ActiveRecord as reference type then you need to have a getModel method in that class as well if you want to access that method. If you are never going to instantiate an ActiveRecord as such you can make it abstract and define the getModel method abstract. If you don't have any implementation logic in ActiveRecord you could make it an interface as well.
public abstract class ActiveRecord {
public abstract Model getModel();
}
public class Player extends ActiveRecord {
#Override
public Model getModel() {
...
}
}
You're making life way too hard for yourself. Java already does reflection for you.
class Parent {
// class content
}
class ChildA extends Parent {
// class content
}
class ChildB extends Parent {
// class content
}
Parent firstInstance = new ChildA();
Parent secondInstance = new ChildB();
Class typeOfFirst = firstInstance.getClass();
Class typeOfSecond = secondInstance.getClass();
As for your null pointer error, in Java (Unlike c++ for example) you have to explicitly initialise every variable with new. Just having private T model; doesn't create an instance of it.
I created an abstract base class. It contains an object which should be extended by any subclasses:
public abstract class AbstractParent {
protected AbstractObject subMePlz;
// ... some fields that all subclasses need
public AbstractParent() {
this.subMePlz = createThisInYourExtendedClass();
}
public abstract AbstractObject createThisInYourExtendedClass();
}
the abstractObject:
public abstract class AbstractObject {
// ... some fields/methods that all subclasses need
}
What I want is to be able to use the extended field in the extended class without casting:
public class ExtendParent extends AbstractParent {
// .. some unique fields
public ExtendParent(){
super();
}
public ConcreteObject createThisInYourExtendedClass(){
return new ConcreteObject();
}
// what I want to do - no cast
public void doSomethingWithSubMePlzWithoutCastingIt() {
System.out.println(this.subMePlz);
}
// what I end up doing - gotta cast
public void doSomethingWithSubMePlzWithoutCastingIt() {
System.out.println((ConcreteObject)this.subMePlz);
}
}
Would needing a comparator change how I should implement this? - I'm thinking a generic comparator for a list of the AbstractObjects that could be used by its subclasses.
It sounds like you need to make it generic:
public abstract class AbstractParent<T extends AbstractObject> {
protected T subMePlz;
// ... some fields that all subclasses need
public AbstractParent() {
this.subMePlz = createThisInYourExtendedClass();
}
public abstract T createThisInYourExtendedClass();
}
public class ExtendParent extends AbstractParent<ConcreteObject> {
...
}
Note that calling non-private methods within a constructor is usually a bad idea - the subclass won't have been fully initialized yet, which can make it difficult to reason about how much you can really rely on.
You have two options:
Abandon the project to declare the field in the superclass. Instead, add an internal abstract "getter" method to your superclass -- basically, AbstractParent should have a method abstract AbstractObject getSubMePlz().
Use generics to set the type of subMePlz in your subclass: define AbstractParent<T> to have a T for its subMePlz field.
Personally, I frequently find option 1 to be very pleasantly extensible -- for example, you can have another subclass that narrows the getSubMePlz() return type without yet declaring it, which can be advantageous.
Why not use this -
super.subMePlz
instead of this -
(ConcreteObject)this.subMePlz
That way, you won't need a cast.
You just could save a copy of the object in the subclass but with the correct class.
public class ExtendParent extends AbstractParent {
ConcreteObject concreteObject;
public AbstractObject createThisInYourExtendedClass(){
ConcreteObject concreteObject = new ConcreteObject();
return concreteObject;
}
public void doSomethingWithSubMePlzWithoutCastingIt() {
System.out.println(concreteObject);
}
...