• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Converting from one subclass to another
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Converting from one subclass to another


  • Subject: Re: Converting from one subclass to another
  • From: David Elliott <email@hidden>
  • Date: Thu, 14 Feb 2008 01:12:33 -0500

Hi David,

On Feb 13, 2008, at 5:06 PM, David Avendasora wrote:

Alright, maybe I'm doing something completely wrong (yeah, yeah, Chuck), but this isn't an apples and oranges thing.

They are both nutritional values, for example: "Calories: 120"


You may have unwittingly just solved your own problem by realizing this. But then again you may not have.


The difference between my two subclasses is simply how the value of the valueQuantity() attribute is derived. In one subclass the user specifies the amount, and in the other it is calculated from the components that make up the product that the nutrition information is tied to. This made me think: different implementations of the same core object means two subclasses.


Then maybe subclassing is the right thing to do. I'm not going to make the blanket statement that it's necessarily wrong in this case. All I can do is try to refine your thoughts on the matter. The best question to ask yourself is whether or not it is appropriate for the user to choose before creating your subclass. If so, then you are fine. It sounds like it may be the case that you could easily ask the user whether he wanted to add a new fixed nutritional value or one calculated from the ingredients. If he chooses to add a calculated one, you may not even display the edit page for it. If he chooses to add a fixed one then you go ahead and display the form.


I think the problem you were originally seeing is that EOF won't necessarily prevent you from creating an object of the abstract NutritionalValue class. So make sure you code is set up to create the appropriate sub class.

If you cannot decide _before_ creating the object that will go into the nutritionalValues relationship of your NutritionalBlock then subclassing is not appropriate. If you can decide it, then subclassing may very well be appropriate. If you actually create the object with the right type to begin with then you won't have the weird problem you were originally having which is that the object only takes on its real class after it is refaulted and

I think the best thing I could do is throw the whole inheritance structure out and simply put an "if" clause on the valueQuantity() method that returns the calculated value if nutritionValueType() returns "Calculated", or simply change nutritionValueType() to an isCalculated() boolean instead.

Just doesn't seem as cool though. But I guess "working" is even cooler.

Like I said, it all depends. Subclassing is an advanced EOF feature that can be quite useful but you have to understand the limitations. There's very little literature on it and most people suggest to just avoid it entirely which is not always the right thing to do but may be if you cannot wrap your head around it.

-Dave

Dave

On Feb 13, 2008, at 3:57 PM, David Elliott wrote:

Hi David,

I can tell you right now that you're going down a very dangerous path here.

Consider even simple code like this:

MyObject *foo; // from somewhare
foo.setNutritionValueType(...);
// foo is still the old instance.

When you subclass like this you need to know _before_ you create the object which subclass it is to have. To do anything else is to completely defeat the very purpose of subclassing in the first place. If you are using D2W there are little methods you can use to provide the user his choice before actually creating the object. If you are not using D2W then you just ask the user in advance.

One UI pattern I've used is something like this:

Add new: [_] Apple [_] Orange    [+]

Where [+] is a regular button to add the new object to the list and Apple/Orange is a set of radio buttons. You could use a pop-up or whatever else instead. Or you could create an add button for each object.

What you cannot do is create a Fruit and then expect to be able to make it an Apple or an Orange at your whim. It doesn't work that way. Subclassing _might_ be the appropriate thing to do in your case but it's a very advanced feature of EOF that you have to plan for very well.

One other thing. If the attributes are the same regardless of the type (and by this example, they seem to be) then subclassing is the wrong thing to do entirely. If you want different behavior for different nutrition types based on the same set of attributes then I suggest you break your logic into a separate class.

For example:

class Fruit {
...
	static abstract class Calculator {
		abstract void doSomething(Fruit fruit);
	};
	static class AppleCalculator extends Calculator {
		...
	};
	static class OrangeCalculator extends Calculator {
		...
	};

static NSDictionary _calculatorForType = new NSDictionary(new String[]
{ "APPLE"
, "ORANGE
}, new Calculator[]
{ new AppleCalculator()
, new OrangeCalculator()
});
...
};


You might even implement a cover method like so:
static Calculator calculatorForType(FruitType ft)
{
return (Calculator)_calculatorForType.valueForKey(ft.fruitTypeCode());
}


That will get you polymorphism (thus allowing you to avoid nasty switch or if/elif) without requiring the objects themselves have their own distinct types.

Note that the above isn't compiled, it's just a general example I typed straight into this mail. Also note I've been doing more C++ than Java coding lately so I probably have semicolons where I don't need them.

There's other ways to do it too. For example, you can give each object its own instance of Calculator in which case it will be easier to make it a non-static inner class and acually store the pointer to it as a _calculator i-var or something of the sort.

It all really depends on how much state you need or do not need to put in the separate Calculator class.

-Dave

On Feb 13, 2008, at 3:26 PM, David Avendasora wrote:

Well, I've got it working, somewhat. I'm creating a new instance of the other subclass, copy all the attributes and relationships over, then delete the old instance.

The problem I'm having is that I'm somehow getting two instances of the target subclass. Maybe someone can look at this code and tell me what I'm doing wrong.

public void setNutritionValueType(NutritionValueType aValue) {
if (nutritionValueType() == null || aValue == null) {
super.setNutritionValueType(aValue);
} else if (aValue != nutritionValueType()) {
CalculatedNutritionValue nv = new CalculatedNutritionValue();
editingContext().insertObject(nv);
nv.setIsSuspect(isSuspect());
nv.addObjectToBothSidesOfRelationshipWithKey(nutritionBlock(), "nutritionBlock");
nv.addObjectToBothSidesOfRelationshipWithKey(nutritionElement(), "nutritionElement");
nv.addObjectToBothSidesOfRelationshipWithKey(aValue, "nutritionValueType");
nv.setSortOrder(sortOrder());
nv.addObjectToBothSidesOfRelationshipWithKey(unitOfMeasure(), "unitOfMeasure");
nv.setValueQuantity(valueQuantity());
editingContext().deleteObject(this);
}
}


It seems very simple. I just don't get where I'm getting a second instance. If I save the EditingContext, I do get two new records in the DB.

Any guesses? Anyone?

Dave

On Feb 13, 2008, at 3:01 PM, Ken Anderson wrote:

David,

I've been down this path many times, and my current recommendation is to just have some kind of type on the object that identifies it as one or the other. I have a situation where I store the class name of a 'calculator' class in the EO, and then dynamically call static methods on that class to do the heavy lifting.

Ken

On Feb 13, 2008, at 11:15 AM, Mike Schrag wrote:

I could just create a new object of the new class and delete the existing one
yes

What is the best way to get WO to pickup the subclass change immediately?

Or is this just a bad way of doing things?
yes

Inheritance hierarchy is to be treated like a PK -- It's an unchanging attribute of an EO. In fact, it's actually part of the EOGlobalID.

What you're describing is very similar to the Employee vs Manager modeling problem. The general consensus is that when an Employee becomes a Manager, it's not changing types, it's changing Roles, so it's actually a Person=>Role, where Role is Manager or Employee and you are just changing the relationship, not the intrinsic type.

You should consider type to be immutable for your own safety and the safety of those around you. The correct way is to delete your old class and make a new one, or maintain a relationship to (something like) a NutrionValueCalculator that changes (if there is a lot of other state in this object other than just this value).

ms

_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden

_______________________________________________ Do not post admin requests to the list. They will be ignored. Webobjects-dev mailing list (email@hidden) Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden



_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
@tgwbd.org


This email sent to email@hidden





_______________________________________________ Do not post admin requests to the list. They will be ignored. Webobjects-dev mailing list (email@hidden) Help/Unsubscribe/Update your Subscription: This email sent to email@hidden
References: 
 >Converting from one subclass to another (From: David Avendasora <email@hidden>)
 >Re: Converting from one subclass to another (From: Mike Schrag <email@hidden>)
 >Re: Converting from one subclass to another (From: Ken Anderson <email@hidden>)
 >Re: Converting from one subclass to another (From: David Avendasora <email@hidden>)
 >Re: Converting from one subclass to another (From: David Avendasora <email@hidden>)

  • Prev by Date: Re: Servlet HttpSession in webobjects?
  • Next by Date: Re: DirectAction & User login Questions.
  • Previous by thread: Re: Converting from one subclass to another
  • Next by thread: Re: Converting from one subclass to another
  • Index(es):
    • Date
    • Thread