Java Forum / General / December 2007
Interface Delegation or ??
Rob McDonald - 15 Dec 2007 05:40 GMT I am constructing a class hierarchy where I would like to extend a runtime determined base class.
Lets say I have an Interface, IPoint.
I implement two classes
class Point2D implements IPoint class Point3D implements IPoint
Then, I want to create a new class, Vertex, which extends from one of the PointND's. I don't want to have to implement two Vertex classes (one for each PointND).
Right now, my solution is to use interface Delegation
class Vertex implements IPoint{ protected IPoint p; Vertex(IPoint p){ this.p=p; } // Wrap all the IPoint methods to point to this.p }
Is there any other syntactic mechanism to accomplish this in Java? Is this the right way? Are there some other keywords I should search for that I'm missing?
TIA,
Rob
REE9opdZ@gmail.com - 15 Dec 2007 17:23 GMT > I am constructing a class hierarchy where I would like to extend a > runtime determined base class. [quoted text clipped - 28 lines] > > Rob Hello Rob,
It is hard to see exactly what you are trying to accomplish. Here are some thoughts.
(1) Why do you need a separate class for vertices? Why not just use an IPoint? (2) Even if you need a separate vertex class, if you can implement all the vertex methods with only a reference to an IPoint (no references to Point2D, Point3D, etc) then your method seems sound. (2) Given that you need a separate vertex class and you need to refer to , you could probably use generic types: interface Vertex < P extends IPoint > { ... }.
I hope this helps.
Emory Merryman External Concepts Guild
Rob McDonald - 15 Dec 2007 18:03 GMT On Dec 15, 9:23 am, REE9o...@gmail.com wrote:
> > I am constructing a class hierarchy where I would like to extend a > > runtime determined base class. [quoted text clipped - 47 lines] > Emory Merryman > External Concepts Guild This is just a simplified example for discussion. I will lay out a bit more for context.
The difference between a IPoint and IVertex is connectivity information.
A point is just a location in space, whereas a vertex is a member of some segment. The Vertex class will keep a list of segments it belongs to.
At the next level, there will be segments and edges. A segment is just an ordered set of vertices. There will be different implementations for straight (2-point) and curved (n-point) segments. There will be geometric methods like segment.length().
Edges will be extended from segments, but edges are used to construct polygons. Consequently, edges will have a list of polygons it belongs to.
At the next level, there will be polygon and face. A polygon is purely geometric, a set of edges. There will be specific implementations for triangle and quad, and a generic implementation for an n-gon. A face is a member of a surface, and will contain a list of surfaces it belongs to.
I would like this hierarchy to be generic to 2D vs. 3D, straight segments vs. quadratic vs. cubic vs. spline segments. Polygons with 3- edges, 4-edges, and n-gon. As well as planar vs. curved polygons.
A top level surface should be able to be constructed from mixing & matching some of these levels (say triangles and quads, not 2D and 3D). Furthermore, I don't want to have to have a derived class...
surfaceOfTrisWithQuadEdges3D surfaceOfQuadsWithStraightEdges3D
etc. for every combinatorial possibility.
I hope this helps frame the problem better. I will look into the use of generics for this.
Rob
Lew - 15 Dec 2007 18:30 GMT > The difference between a IPoint and IVertex is connectivity > information. > > A point is just a location in space, whereas a vertex is a member of > some segment. The Vertex class will keep a list of segments it > belongs to. It sounds like your solution where Vertex has-a Point is appropriate.
You might be able to abstract the dimensionality of a Point by making it a parameter or a generic parameter.
 Signature Lew
Rob McDonald - 15 Dec 2007 18:36 GMT > > The difference between a IPoint and IVertex is connectivity > > information. [quoted text clipped - 7 lines] > You might be able to abstract the dimensionality of a Point by making it a > parameter or a generic parameter. Thanks for the tip.
I have certainly been thinking of abstracting the dimensionality of Point in some manner.
As you probably guessed, I was looking for an OO technique which would extend throughout the geometry & connectivity hierarchy. Point/Vertex was just the simplest example.
Rob
Lew - 15 Dec 2007 18:52 GMT Lew wrote:
>> It sounds like your solution where Vertex has-a Point is appropriate. You mentioned that you delegate "Pointish" methods in Vertex to the internal Point. You might be able to expose the Point directly via a getPoint() method in the Vertex, depending on how dangerous you think that is.
 Signature Lew
Rob McDonald - 15 Dec 2007 20:37 GMT > Lew wrote: > >> It sounds like your solution where Vertex has-a Point is appropriate. > > You mentioned that you delegate "Pointish" methods in Vertex to the internal > Point. You might be able to expose the Point directly via a getPoint() method > in the Vertex, depending on how dangerous you think that is. I would prefer to be able to treat Vertex with is-a semantics rather than an explicit getPoint() has-a approach.
However, there may someday be the need for runtime type checking of the underlying Point. I was thinking of implementing a getPointClass() method in Vertex which would simply...
public class Vertex implements IPoint{ IPoint p; public Vertex(IPoint p){ this.p = p; }
public Class getPointClass(){ return p.getClass(); }
// All the wrappers around p to implement IPoint. }
Of course, right now I am very unsure of how generics come into this. The standard
public final Class <? extends Object> getClass()
gives me the willies...
I guess you would use it something like this?
Class c <? extends IPoint> = vtx.getPointClass();
Rob
Lew - 15 Dec 2007 20:50 GMT > However, there may someday be the need for runtime type checking of > the underlying Point. I was thinking of implementing a [quoted text clipped - 9 lines] > return p.getClass(); > } When you start branching based on explicit knowledge of a class, it's time to rethink your object model, as it is almost always wrong in that case.
> I would prefer to be able to treat Vertex with is-a semantics rather > than an explicit getPoint() has-a approach. Then generics are likely your answer, as REE9opdZ@gmail.com suggested.
 Signature Lew
Rob McDonald - 15 Dec 2007 21:12 GMT > When you start branching based on explicit knowledge of a class, it's time to > rethink your object model, as it is almost always wrong in that case. You very well may be right on this point.
> > I would prefer to be able to treat Vertex with is-a semantics rather > > than an explicit getPoint() has-a approach. > > Then generics are likely your answer, as REE9o...@gmail.com suggested. How can I use generics to do this? I want to extend from an arbitrary base class (known to implement some interface).
My experience with generics is very much in the spirit of Collections<T>. Which really doesn't seem to apply here.
I guess I'll go hit the books some more, but I thought this was the question I asked in the first place.
Rob
External Concepts Guild - 18 Dec 2007 18:51 GMT > > Then generics are likely your answer, as REE9o...@gmail.com suggested. > [quoted text clipped - 8 lines] > > Rob Below is sample code. This code works for one dimensional space (points are BigDecimals). You can extend it to other dimensions by (1) implementing some class to represent the higher dimension points and (2) implementing some DistanceMetric class that works on the new Point class. If you do 1 and 2 correctly, you should be able to use the ListSegmentFactory without any further modifications.
I hope this helps.
Emory Merryman External Concepts Guild
/** * Useful for making things. **/ interface Factory < R , P , E extends java . lang . Exception > { public abstract R make ( final P p ) throws E ; }
/** * Can be used to calculate the distance between two Points **/ interface DistanceMetric < P , R extends java . lang . Comparable < R
{ public abstract R distance ( final P p1 , final P p2 ) ; }
/** * Calculates the euclidean distance between two one dimension points * represented by java.math.BigDecimal. **/ final class Distance1D implements DistanceMetric < java . math . BigDecimal , java . math . BigDecimal > { public final java . math . BigDecimal distance ( final java . math . BigDecimal p1 , final java . math . BigDecimal p2 ) { final java . math . BigDecimal difference = p1 . subtract ( p2 ) ; final java . math . BigDecimal distance = difference . abs ( ) ; return ( distance ) ; } }
/** * Segments have length. **/ interface Segment < P , R extends java . lang . Comparable < R > > { public abstract R length ( ) ; }
/** * Makes a Segment based on the specified ordered list of points. * Uses the specified distance metric to calculate the length. **/ final class ListSegmentFactory < P > implements Factory < Segment < P , java . math . BigDecimal > , java . util . List < P > , java . lang . RuntimeException > { ListSegmentFactory ( final DistanceMetric < P , java . math . BigDecimal > dm ) { super ( ) ; this . dm = dm ; }
private DistanceMetric < P , java . math . BigDecimal > dm ;
public final Segment < P , java . math . BigDecimal > make ( final java . util . List < P > points ) { final Segment < P , java . math . BigDecimal > segment = new Segment < P , java . math . BigDecimal > ( ) { public final java . math . BigDecimal length ( ) { java . math . BigDecimal length = java . math . BigDecimal . ZERO ; for ( int i = 1 ; i < points . size ( ) ; i ++ ) { final P p1 = points . get ( i - 1 ) ; final P p2 = points . get ( i ) ; final java . math . BigDecimal distance = dm . distance ( p1 , p2 ) ; length = length . add ( distance ) ; } return ( length ) ; } } ; return ( segment ) ; } }
Lew - 21 Dec 2007 16:12 GMT > Below is sample code. This code works for one dimensional space > (points are BigDecimals). You can extend it to other dimensions by [quoted text clipped - 4 lines] > > I hope this helps. It's a great example, but the embedded TABs in the listing push some of the source text way off to the right, and hurt readability. I suggest indentation using spaces only, and keep it fairly narrow; an indent of between two to four spaces suffices for Usenet.
> /** > * Useful for making things. [quoted text clipped - 11 lines] > public abstract R distance ( final P p1 , final P p2 ) ; > }
> /** > * Segments have length. [quoted text clipped - 3 lines] > public abstract R length ( ) ; > } It doesn't look like interface Segment uses the P parameter at all. Perhaps it's safe to drop it?
To other readers: take note that these interfaces have package-private access. This automatically restricts all use of these interfaces to the package (no need for messy access decorations on the individual methods - Java is convenient this way.)
 Signature Lew
tam@milkyway.gsfc.nasa.gov - 21 Dec 2007 17:32 GMT > > /** > > * Useful for making things. [quoted text clipped - 26 lines] > -- > Lew Not entirely. As we discussed in another thread, declaring a public class which implements these interfaces, means all of the interface methods must also be visible to the public though the existence of the interfaces themselves may be hidden. You can explicitly hide the methods using delegation but then you will need to be aware of this implementation whenever you do want to use the interfaces. A public class can never explicitly implement an interface and simultaneously hide the associated methods.
Regards, Tom McGlynn
Lew - 22 Dec 2007 01:03 GMT >>> /** >>> * Useful for making things. [quoted text clipped - 34 lines] > class can never explicitly implement an interface and simultaneously > hide the associated methods. The interface /per se/ is hidden to the public, so cannot be used as a supertype or otherwise directly accessed outside the package.
It is true that public methods declared to implement the interface in a public class will be visible to the outside, but that clearly would be a deliberate decision by the implementor. It would also argue for making the interface public. If the interface is package-private, it is usually because it is used only in a package-private context.
It remains true that all uses of the package-private interface will "entirely" be package-local. There's no way around that. It may well be that other classes exposes implementing methods to the public; that doesn't change the truth of the assertion that the interface itself remains hidden.
 Signature Lew
tam@milkyway.gsfc.nasa.gov - 22 Dec 2007 15:42 GMT > t...@milkyway.gsfc.nasa.gov wrote: ...
> > Not entirely. As we discussed in another thread, declaring a public > > class which implements these interfaces, means all of the interface > > methods must also be visible to the public though the existence of the > > interfaces themselves may be hidden. ...
> The interface /per se/ is hidden to the public, so cannot be used as a > supertype or otherwise directly accessed outside the package. > > It is true that public methods declared to implement the interface in a public > class will be visible to the outside, but that clearly would be a deliberate > decision by the implementor. ...
> Lew I was responding to these words a couple of messages upstream...
--To other readers: take note that these interfaces have package- private access. --This automatically restricts all use of these interfaces to the package (
>>>> no need for messy access decorations on the individual methods <<< -- Java is convenient this way.)
The "no need..." might suggest to a reader that the methods were in fact hidden by making the interface package protected and that's what I tried to clarify.
Also, when you say:
> It is true that public methods declared to implement the interface in a public > class will be visible to the outside, but that clearly would be a deliberate > decision by the implementor. I'm not clear what you're getting at. Certainly a coder explicitly chooses to include an interface, but once they do they have no choice about implementing the methods as public. When implementing a package level interface in a public class a code must expose the package methods.
Typical interfaces consist of three elements two of which can be hidden from the public (absent reflection) in a package level interface:
The interface type Interface-defined constants [I haven't checked this but I believe it to be so]
and one which must be made visible to the public
The methods
Regards, Tom McGlynn
Lew - 22 Dec 2007 16:36 GMT > I'm not clear what you're getting at. Certainly a coder explicitly > chooses to include an interface, but once they do they have no choice > about implementing the methods as public. When implementing a package > level interface in a public class a code must expose the package > methods. Well, there's your mistake right there. You're not supposed to implement package-level interfaces in public classes. Package-level interfaces are for package-level classes, otherwise for public classes use a public interface.
If you want to lock down certain parts of the implementation, which is what methods at less than public access are for, use an abstract class as the parent and put those parts there.
Interfaces do not exist for the purpose of specifying implementation, thus they do not support method-level access less than public. Period. That's their whole point. If you want an interface to be used only within the package, you declare the whole interface package-private, and use it only for package-private classes.
The point of an interface is that it makes a supertype with all method signatures defined, but *not* implementation. Having it support less-than-public methods would defeat its purpose.
Again, if your interface is not public, then neither should its implementors be. That's the Java idiom. It's abstract classes that you want, in order to nail down parts of the implementation.
 Signature Lew
tam@milkyway.gsfc.nasa.gov - 23 Dec 2007 17:57 GMT ...
> Well, there's your mistake right there. You're not supposed to implement > package-level interfaces in public classes. Package-level interfaces are for [quoted text clipped - 10 lines] > package-private classes. > Lew Hmmm... I don't think I consider the visibility of a method part of its implementation -- any more than say its return type.
Regardless, I don't think the visibility of the interface makes much practical difference if the interface is only implemented in package level code.
E.g., let's consider that we've adopted your rule and package visible interfaces are implemented only in package visible classes. Clearly the interface is not visible to the public, nor can any implementation of any method in the interface be accessed outside the package.
Now let's make the interface public. We still want to restrict use the interface to one package, but we're exploring what making it public does. So what happens?
The clearest change is that external(to the package) users can now access the constants defined in the interface. That's a real change and its certainly useful to restrict visibility of constants in some cases, but our dicussion heretofore has focussed on how methods are affected. What happens there?
Public users still cannot directly access the implementation of any of the methods, because the class protections for each of the implementing classes are still set to package level.
Ah, but they can now create their own implementation of the interface and pass it in to some public method that takes the interface as an input and thus get access to something they weren't able to get to before... I.e.,
package pack; public class SomeClass { public void someMethod(HiddenInterface x) {...} } ... package otherpack; public class NewClass implements HiddenInterface { void crackingMethod() { someMethod(this); } }
where HiddenInterface is the interface that we just made public.
Here crackingMethod is able to inject an instance of the new user class and clearly might have access where it didn't before. So this seems new...
That's right, but why was there a public method in a public class that used a type that didn't wasn't supposed to be available to the public? The only legitimate reason I might see is that 'someMethod' is itself defined in an interface so it needed to be public. But if it's in an interface that uses HiddenInterface, then presumably this second interface is also only supposed to be used within the package so by hypothesis we shouldn't be implementing it in a public class.
So what did the package level protection get us: It hid constants and it's probably useful as a bit of documentation: it can indicate we should limit visibility of certain classes and methods, but at best it should act as kind of backup, cleaning up if we make errors in some of our visibility specifications for methods in public classes.
That said, I'm not sure I agree with your first statement above... Users should feel free to implement package level interfaces in public classes. There may be many cases where that's fine. All I've ever said is that if they do so, they need to recognize that the implementation of the methods of the interface must be visible to the public regardless of the visibility of the interface itself.
I can see reasonable cases for any combination of public and package classes implementing public and package interfaces, but the interactions of the visibilities of the classes, interfaces and methods are rather subtle. And all this is before we consider how inheritance might affect all of this!
Regards, Tom McGlynn
Lew - 23 Dec 2007 21:00 GMT > Hmmm... I don't think I consider the visibility of a method part of > its implementation -- any more than say its return type. Interfaces don't have implementation.
> Regardless, I don't think the visibility of the interface makes much > practical difference if the interface is only implemented in package > level code. It makes a difference to the visibility of the interface type, which is the reason one mucks with visibility.
> E.g., let's consider that we've adopted your rule and package visible > interfaces are implemented only in package visible classes. Clearly > the interface is not visible to the public, nor can any implementation > of any method in the interface be accessed outside the package. So far, so good.
> Now let's make the interface public. We still want to restrict use > the interface to one package, but we're exploring what making it > public does. So what happens? There's your problem right there. If you want to restrict use of the interface to just the package, why are you making it public? That makes no sense.
> The clearest change is that external(to the package) users can now > access the constants defined in the interface. That's a real change You should never define constants in an interface. That antipattern is an Item in Joshua Bloch's /Effective Java/. Interfaces are there to define contract, not implementation. Putting constants in an interface is an abuse.
> and its certainly useful to restrict visibility of constants in some > cases, but our dicussion heretofore has focussed on how methods are [quoted text clipped - 3 lines] > the methods, because the class protections for each of the > implementing classes are still set to package level. Because these classes, *by design*, are not intended for public use.
> Ah, but they can now create their own implementation of the interface > and pass it in to some public method that takes the interface as an > input and thus get access to something they weren't able to get to > before... I.e., No previous implementation of the interface can have been passed to a public method in a public class, since none of the type or its subtypes were publicly visible. Your scenario cannot happen.
> package pack; > public class SomeClass { > public void someMethod(HiddenInterface x) {...} > } When the 'HiddenInterface' had package-private access, and was not in package 'pack', this method would have raised a compiler error.
> ... > package otherpack; [quoted text clipped - 8 lines] > class and clearly might have access where it didn't before. So this > seems new... To what? Access to what? All the previous classes had package-private access. Calling the method 'crackingMethod()' doesn't make it magically able to crack anything.
Furthermore, why was the interface promoted to public access? Surely such a decision is weighed against the cost of changes. But worrying about cracking into a package-private implementation isn't one of them. In fact, it's one of the most common idioms in Java to have package-private or private implementations of public interfaces. What you tout as a disadvantage is actually one of the great strengths of the language.
> That's right, but why was there a public method in a public class that > used a type that didn't wasn't supposed to be available to the [quoted text clipped - 3 lines] > second interface is also only supposed to be used within the package > so by hypothesis we shouldn't be implementing it in a public class. Nor could any public method of a public class from a different package make use of a non-public interface.
> So what did the package level protection get us: It hid constants and Constants that should never be defined in an interface in the first place.
> it's probably useful as a bit of documentation: it can indicate we > should limit visibility of certain classes and methods, but at best it > should act as kind of backup, cleaning up if we make errors in some of > our visibility specifications for methods in public classes. It isn't "documentation", it's a fundamental decision about the use of a type whether to make it public or package-private.
> That said, I'm not sure I agree with your first statement above... > Users should feel free to implement package level interfaces in public No, they shouldn't. If it's in a different package, you get a compiler error. The reason to make something package-private is to restrict its visibility. If you don't restrict the visibility, then you have no reason to declare it with restricted visibility. Your suggestion contradicts the very point of declaring restricted visibility.
> classes. There may be many cases where that's fine. All I've ever > said is that if they do so, they need to recognize that the > implementation of the methods of the interface must be visible to the > public regardless of the visibility of the interface itself. Programmers need to be aware of the implications of the visibility rules in their chosen language, yes. If you choose to implement a package-private interface in a public class, that's fine, but users of the public class will not have access to the supertype. To them, the methods will just look like regular, non-contracted methods, just as if there were no interface involved. Indeed, one must presume that is intentional, else why do such a thing?
> I can see reasonable cases for any combination of public and package > classes implementing public and package interfaces, but the > interactions of the visibilities of the classes, interfaces and > methods are rather subtle. The actual interactions are precisely specified for Java.
> And all this is before we consider how inheritance might affect all of > this! Interfaces exist for the whole purpose of inheritance. This is not "before we consider" inheritance; in fact, my advice all along in this and the other thread was based on the notion of inheritance. It's fundamental to the entire conversation so far. It is the entire point. It is the heart of the matter, and has been from the start. Not only are we not "before" such consideration, we are steeped in it, drowning in it. It is the only thing under consideration.
Not dealing with the notion of inheritance in talking of package-private visibility for interfaces and abstract classes (see upthread) invalidates any possibility of understanding the issues involved, since the issues involved *are inheritance issues*.
From the start, intrinsically.
 Signature Lew
Lew - 23 Dec 2007 21:38 GMT tam@milkyway.gsfc.nasa.gov wrote:
>> Ah, but they can now create their own implementation of the interface >> and pass it in to some public method that takes the interface as an >> input and thus get access to something they weren't able to get to >> before... I.e.,
> No previous implementation of the interface can have been passed to a > public method in a public class, since none of the type or its subtypes > were publicly visible. Your scenario cannot happen. > ... > The actual interactions are precisely specified for Java. If the public class is in the same package as the package-private interface, it can get away with exporting the interface type via a public method.
While technically legal, it does raise a warning in my IDE. (NetBeans, as it happens, but I'm pretty sure Eclipse supports this warning also.)
"Exporting non-public type through public API"
This pathological example does just that in the methods that set and get an 'InnerFace' instance. It makes 'Fimpl' a little difficult to use from outside the package; the client code has to treat the signatures as though they used 'Object' instead of 'InnerFace' and they don't have access to the supertype, specifically not to its methods. (Not through the supertype reference, at least.)
While this usage is barely legal, the best advice is not to do it. Don't expose restricted visibility types to wider examination. If you make a type package-private, it's for a reason. It's a type.
public class Fimpl implements Runnable { /** Keep the interface on the down-low. */ /* p-p */ static class NestedFimpl implements InnerFace { @Override public void foo() { System.out.println( "NestedFimpl.foo()" ); } }
private volatile InnerFace face;
/** No-arg constructor. */ public Fimpl() { this( null ); }
/* p-p */ Fimpl( InnerFace f ) { face = (f == null? new NestedFimpl() : f); }
/* p-p */ void setFace( InnerFace f ) { face = (f == null? new NestedFimpl() : f); }
/* p-p */ InnerFace getFace() { return face; }
/** Delegate an action to <code>foo()</code>. */ @Override public void run() { face.foo(); }
/** Expose the package-private interface to the whole world. * @param f non-visible type, pass an <code>Object</code>. */ public void setInnerFace( InnerFace f ) { setFace( f ); }
/** Expose the package-private interface to the whole world. * @return non-visible type, treat as <code>Object</code>. */ public InnerFace getInnerFace() { return getFace(); } }
 Signature Lew
Codedigestion - 23 Dec 2007 23:40 GMT > t...@milkyway.gsfc.nasa.gov wrote: > >> Ah, but they can now create their own implementation of the interface [quoted text clipped - 90 lines] > -- > Lew Peace Rob,
I'm not exactly sure what you're trying to do, but as I can ascertain from your first post, it seems that you're trying to use a Design Pattern called the "Strategy Pattern". I think this is what you're looking for, perhaps:
-----------------------------
public interface IPoint { public void dosomething(); }
-----------------------------
public class Point2D implements IPoint { public void doSomething() { System.out.println("I'm 2D.") } }
-----------------------------
public class Point3D implements IPoint { public void doSomething() { System.out.println("I'm 3D.") } }
-----------------------------
public abstract class Vertex { IPoint iPoint;
public Vertex(){ }
public void pleaseDoSomething() { iPoint.doSomething(); }
}
----------------------------
public 2DVertex extends Vertex{ doSomething = new Point2D(); }
----------------------------
public 3DVertex extends Vertex{ doSomething = new Point3D(); }
----------------------------
I don't know if this code will even work. Quite frankly, I'm new to this myself, but I think this may be what you're looking for; The Strategy Pattern. Especially if you want to program to 'composition' instead of 'implementation'. I've found out about all of this from Head First Design Patterns: http://www.amazon.com/gp/product/0596007124?ie=UTF8&tag=myprfothusst1-20&linkCod e=xm2&camp=1789&creativeASIN=0596007124
Let me know how this works for ya', would ya'? Well this stuff makes a lot more sense in the book. Perhaps I've done a poor job of explaining it. I think if you do a google search for "Strategy Design Patterns" you may get better examples, God willing.
God Bless,
shree
Codedigestion - 23 Dec 2007 23:41 GMT > > t...@milkyway.gsfc.nasa.gov wrote: > > >> Ah, but they can now create their own implementation of the interface [quoted text clipped - 167 lines] > > shree package wikipedia.patterns.strategy;
// MainApp test application class MainApp {
public static void main(String[] args) { Context context;
// Three contexts following different strategies context = new Context(new ConcreteStrategyA()); context.execute();
context = new Context(new ConcreteStrategyB()); context.execute();
context = new Context(new ConcreteStrategyC()); context.execute(); } } // The classes that implement a concrete strategy should implement this // The context class uses this to call the concrete strategy interface IStrategy { void execute(); }
// Implements the algorithm using the strategy interface class ConcreteStrategyA implements IStrategy { public void execute() { System.out.println( "Called ConcreteStrategyA.execute()" ); } }
class ConcreteStrategyB implements IStrategy { public void execute() { System.out.println( "Called ConcreteStrategyB.execute()" ); } }
class ConcreteStrategyC implements IStrategy { public void execute() { System.out.println( "Called ConcreteStrategyC.execute()" ); } }
// Configured with a ConcreteStrategy object and maintains a reference to a Strategy object class Context { IStrategy strategy;
// Constructor public Context(IStrategy strategy) { this.strategy = strategy; }
public void execute() { strategy.execute(); } }
--------------------------------------------- http://en.wikipedia.org/wiki/Strategy_pattern
Rob McDonald - 27 Dec 2007 04:39 GMT > Peace Rob, > [quoted text clipped - 72 lines] > > shree Shree,
Thanks for the help and the thoughts. I think you are close to demonstrating the interface delegation concept I mentioned, but there is one hitch.
I don't want to have a separate Vertex class for 2D and 3D. That way, I can have 2D and 3D Point classes (and maybe 1D, and ND) and then just make a Vertex with whatever Point it needs. Ideally, the Vertex implementation will be very simple.
Normally in a class hierarchy, you start with simple, abstract things and build to more specific and complex implementations. In that pattern, you naturally end up with many implementations at your final level of abstraction. Swing provides an example of this... (from the Java API docs)
java.lang.Object extended by java.awt.Component extended by java.awt.Container extended by javax.swing.JComponent extended by javax.swing.AbstractButton extended by javax.swing.JToggleButton extended by javax.swing.JRadioButton
A JRadioButton is-a lot of different things. As you progress up the chain, each level implements certain methods/interfaces for you. At the final level of the chain, there are a very large number of classes which are JComponent's.
You can visualize this as a tree, fanning out to have many branches at the top.
In my situation, things are a bit different (first, it isn't nearly as complex as Swing). In my structure, the underlying class has more options/complexity than the top level. Instead of a tree, we have a pyramid or a root system, with lots of things at the bottom combining to one thing at the top.
So, what I would like, is the ability to have a variety of implementations at the lower level (Point), but then bring them all together under a single Vertex implementation. To me, it is very important to have only one Vertex implementation.
Your example can achieve this by using the interface delegation construct I mentioned earlier. Basically, change your Vertex constructor to accept a Point as its argument. The program will still have to instantiate the correct Point2D or Point3D, and then pass it to the Vertex at the time of instantiation.
Hopefully this all makes more sense when applied to Segment/Edge, Poly/ Face etc.
Rob
Codedigestion - 27 Dec 2007 13:32 GMT > > Peace Rob, > [quoted text clipped - 127 lines] > > Rob Peace Rob,
As I'm new to all of this, I was able to understand more from you than from myself. :) It seems as if you're looking to build some sorta' abstraction layer with a single entry point to access a huge hierarchy of capability limited down to a specific functionality. Perhaps, it would be one of the other design patterns. I've only been able to read 3 patterns thus far. Will keep a lookout for you, sir...
God Bless,
shree
tam@milkyway.gsfc.nasa.gov - 24 Dec 2007 03:35 GMT My suspicion is that Lew and I are at the point where we're talking past each other so I'll leave it here.
However in closing I would like to correct the idea I put forward that there would not be a 'legitimate' use for code like:
package pack; interface HiddenInterface {...}
public class SomeClass { public void someMethod(HiddenInterface x) {...} }
I'd suggested that this was legal but couldn't see any reason for it, while Lew noted that NetBeans cautions against it and also suggested that it wasn't a good idea. Despite our agreement, I now suspect we were both wrong. Such a usage might be perfectly appropriate if we add some additional interfaces to the package, e.g.,
final public interface Visible1 extends HiddenInterface {...} final public interface Visible2 extends HiddenInterface {...}
Then for example we might have:
package otherpack; public class AnotherClass implements Visible1 { ... pack.SomeClass xxx = ... xxx.someMethod(this); ... }
Restricting the base interface to package visibility means that all of the public interfaces must be declared in the pack package (assuming we make all the derived interfaces final). So that package still can limit the valid interfaces. We need to use the base interface in the method signature to assure that we can handle all of the sub- interfaces.
I could imagine something like this being needed in sophisticated factory patterns though I've never had requirements for such - I very rarely extend interfaces at all. It seems reasonably straightforward but I've not explicitly checked that it's legal. Since NetBeans looks at the entire project I'd expect it to notice the additional interfaces and give up it's warning, but again I haven't checked.
While this is another reason one might use package interfaces, it does not materially affect my earlier discussion of the extent to which package level interfaces and their contents are visible to the public.
Merry Christmas to all! Tom McGlynn
Rob McDonald - 27 Dec 2007 00:02 GMT OP back online after being away for a few days (also got lost in a sea of spam for a while there).
All these posts will take me a bit to digest, but thanks to all who have kept it active.
I'm sure these answers will spawn more questions.
Rob
Daniel Pitts - 18 Dec 2007 19:56 GMT > I am constructing a class hierarchy where I would like to extend a > runtime determined base class. [quoted text clipped - 28 lines] > > Rob There is no clean way to extend at runtime. While a Vertex may seem like a Point to you, its really not a Point. A Vertex has a location, and has related Edges, where a Point simply has a Location. Perhaps you really want a Location2d and Location3d, and then a class Point<L extends Location>, and class Vertex<L extends Location>
If you think about abstracting the concept of a location from the concept of a point/vertex, you simply this model a bit.
Mark Space - 19 Dec 2007 22:13 GMT > There is no clean way to extend at runtime. While a Vertex may seem > like a Point to you, its really not a Point. A Vertex has a location, [quoted text clipped - 4 lines] > If you think about abstracting the concept of a location from the > concept of a point/vertex, you simply this model a bit. I was sort of thinking the same. A point is a fairly lightweight concept and trying to extend it to a class that add so little to the point might be a misfeature.
I think the OP should consider skipping a Vertex class and going straight for Strips, Meshes, Fans and Polygons. These would naturally have lists of Points (has-a) and should probably implement their own methods for finding edges and adjacent points, because they'll each need slightly different algorithms for best efficiency.
Points might even be implemented internally just by 2d arrays. Operations on points could just be static methods. Don't forget that while fairly small, there is overhead associated with method calls when inheritance might be involved.
Daniel Pitts - 20 Dec 2007 16:24 GMT >> There is no clean way to extend at runtime. While a Vertex may seem >> like a Point to you, its really not a Point. A Vertex has a location, [quoted text clipped - 19 lines] > while fairly small, there is overhead associated with method calls when > inheritance might be involved. Now you've gone a little to far in the opposite direction. It is important to avoid primitive obsession in program design. I think a Vertex class is useful, as it can have a list of Edge objects that connect via itself. Unless you need a specialized algorithm for some reason, use the cleanest abstract approach.
 Signature Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>
Rob McDonald - 27 Dec 2007 04:18 GMT > There is no clean way to extend at runtime. While a Vertex may seem > like a Point to you, its really not a Point. A Vertex has a location, [quoted text clipped - 4 lines] > If you think about abstracting the concept of a location from the > concept of a point/vertex, you simply this model a bit. At this level, I fail to see the difference between a Location and a Point; however, I am more than willing to explore the ideas.
Maybe it would've been better if I had given an example a little higher up the food chain. The segment/edge relationship is a bit more rich than the point/vertex situation. As I discussed in an earlier post, I am interested in exploring this concept throughout the hierarchy.
My general structure concept is borrowed from GTS gts.sourceforge.net/ reference/book1.html . GTS is written in ANSI C, but is brutally object oriented in the style of GTK. Although my structure is patterned off of GTS, I hope to build in a greater level of generality/ abstraction.
Back to the segment/edge relationship. To me, Segments are finite length lines (or curves) in space. All Segments will have a starting and ending vertex. Some Segments will have intermediate vertices. The implementation of Segment should not care what kind of Vertex is used (of course, this is a has-a relationship).
The obvious Segment candidates are Linear, Quadratic, and Spline. Others are of course possible. Furthermore, there are lots of ways to implement each of these types. For example, the quadratic segment could store the three points individually, in an array, or in a list. It could even store the end points and derivative information instead of a 3rd point.
Edges are used to build up polygons. A Poly is essentially a list of Edges. Each Edge contains a list of Polys it is a part of. In a topologically correct closed surface, each Edge should be a part of two Polys.
I want Edge to have an is-a relationship to Segment. However, I expect the Edge implementation to be rather simple, and it should be the same no matter the underlying Segment.
Rob
Roedy Green - 21 Dec 2007 19:41 GMT On Fri, 14 Dec 2007 21:40:55 -0800 (PST), Rob McDonald <rob.a.mcdonald@gmail.com> wrote, quoted or indirectly quoted someone who said :
>Is there any other syntactic mechanism to accomplish this in Java? I thing delegation is the way to fly. Otherwise you would have to implement both interfaces, using dummy implementations that threw UnsupportedOperationException exceptions.
 Signature Roedy Green Canadian Mind Products The Java Glossary http://mindprod.com
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|