algorithmic modeling for Rhino
So imagine the following schema, abstracted for (I hope) clarity and simplicity. I tried three approaches to get it to work, but none seem to do the trick. Is there a programming concept that would get around this? Can anyone give me some insight on implementation?
Custom class
Ingredient
Custom interface
IFood
Method: bake
Method: eat
Custom class A
Pizza : IFood
simple (eg. string or int) properties are set in constructor
bake() and eat() are defined in the class, as one would expect
List<Ingredient> myIngredients;
Custom class B
Lasagna : IFood
simple (eg. string or int) properties are set in constructor
bake() and eat() are defined in the class, as one would expect
List<Ingredient> myIngredients;
The trouble comes when I try to do something like this:
Grasshopper component : "Recipe"
Should accept either custom class A or custom class B, and be able to loop through their ingredients and output a long string.
Method 1:
Recipe component accepts and performs operations on objects of type "IFood", but gives an error because "IFood" does not contain a definition for "myIngredients".
Method 2 (I think this is the right path):
Try adding "List<Ingredient> myIngredients" to "IFood" and get two errors "Interfaces cannot contain fields" and "Inconsistent accessibility: field type 'List<Ingredient>' is less accessible than field 'IFood.myIngredients' "
Method 3:
Try adding a method to "IFood" called "myIngredients". This would be defined in each class that implements the interface and return all the ingredients as a list. Errors: "Inconsistent accessibility: return type 'Ingredient' is less accessible than method 'IFood.myIngredients()' " Also a bunch of errors in the "Recipe" component, where I try to actually use IFood.myIngredients...
Tags:
Method 2 is indeed the right approach. You should never expose fields anyway, add a readonly property to IFood which returns an ingredient collection:
IEnumerable<Ingredient> Ingredients { get; }
You can use List<Ingredient> or Ingredient[] as well of course, I just like to use IEnumerable and implement it as a yield property:
public IEnumerable<Ingredient> Ingredients{
get
{
foreach (Ingredient ingredient in _ingredients)
yield return ingredient;
}
}
This approach prevents callers from changing the ingredient collection without the need to duplicate the collection each time it is accessed.
Incidentally if Ingredient is less accessible than the IFood interface (for example if IFood is public, but Ingredient is internal), then my solution won't work. You'll either have to elevate the accessor of Ingredient to be identical to or higher than IFood, or you need to create a second interface (let's say IIngredientList) which has the same access level. Your components will then need to use this second interface to access the ingredients.
Thanks!
I added a public keyword to Ingredient, and that cleared up the accessor issue, a totally newbie mistake on my part.
I ended up implementing Ingredients as an IList, so I can add additional ingredients, even after initial construction of the class.
If anyone else finds this and is wondering how to do IList, this article is really helpful:
http://stackoverflow.com/questions/4458900/why-it-is-not-possible-t...
Thanks again for your help David!
Welcome to
Grasshopper
Added by Parametric House 0 Comments 0 Likes
Added by Parametric House 0 Comments 0 Likes
Added by Parametric House 0 Comments 0 Likes
Added by Parametric House 0 Comments 0 Likes
Added by Parametric House 0 Comments 0 Likes
© 2024 Created by Scott Davidson. Powered by