Prev: Initializing a Map in an Interface?
Next: Urgent Opening for Senior .Net Engineer position with our direct client in Milpitas, CA
From: Lew on 16 Mar 2010 22:25 markspace wrote: > OK, now I think I see what you are asking. "Should this class be made > "final"". My opinion: no. Never never make a class final unless you > have thought about it and are sure it must be final. > > There's some extra design required when you DON'T make a class final, > but you should always go through that process. The reason is I think > called The Open-Closed Principle, and basically it means that you should > always leave open the possibility that someone will want to extend your > class. Try to let them if at all possible. Other principles aside > ("Prefer composition to extension.") it's pernicious to actually prevent > extension unless you have a good reason. Imo. I reserve the right to prevent extension of my class. My bias formally is to make a class 'final', but in practice I rarely do, and while I don't actually design for inheritance as such, I avoid many pitfalls by 'final' methods, lots of 'private', and the like. The potential damage is contained. Reasonable use by subclasses won't do any harm, and unreasonable use leaves no one but the subclasser to blame. But I'm ready to declare a class 'final' any time. Yep. Just as soon as it matters enough. Ayep. -- Lew
From: markspace on 16 Mar 2010 23:13 Arne Vajh�j wrote: > > The reason that they don't is not because it does not make sense > from an OO perspective - it is because it would really clutter > mathematical code. Since Rhino (the OP) seems somewhat new to Java, I want to add that Arne's comment is speculation. I doubt anyone here knows the actual reason the designers of the Java API chose the static pattern they did. A class with all static methods is a simple, well-understood pattern, and in general software designers like simple, well-understood patterns. What the exact motivating factor was for using it in this case I cannot say.
From: markspace on 16 Mar 2010 23:20 Lew wrote: > but in practice I rarely > do, and while I don't actually design for inheritance as such, I avoid > many pitfalls by 'final' methods, lots of 'private', and the like. The > potential damage is contained. Reasonable use by subclasses won't do > any harm, and unreasonable use leaves no one but the subclasser to blame. > This is a pretty good description how I design classes too, given the normal time pressures a software engineer is under. Just quoted for Rhino's benefit, and in case anyone else wants to comment.
From: Arved Sandstrom on 17 Mar 2010 06:28 markspace wrote: > Lew wrote: > >> but in practice I rarely do, and while I don't actually design for >> inheritance as such, I avoid many pitfalls by 'final' methods, lots of >> 'private', and the like. The potential damage is contained. >> Reasonable use by subclasses won't do any harm, and unreasonable use >> leaves no one but the subclasser to blame. > > This is a pretty good description how I design classes too, given the > normal time pressures a software engineer is under. Just quoted for > Rhino's benefit, and in case anyone else wants to comment. We had a lengthy thread about final not so long ago, although it never hurts to have it again. I'm pretty much with Lew and yourself on this one. I don't normally write public Java libraries; what I do write are classes that go into (or already belong to) moderate to large size custom J2EE apps. The original apps I help maintain and fix up aren't usually well written and most often contain unnecessary and confusing subclasses already - I'm not about to encourage adding more. I'll do exactly what Lew does when I am plugging leaks and tightening yards: I'll privatize methods, make them final occasionally, and every so often make a class final. To me the distinction lies between designing and implementing for Java APIs and implementations for the masses, and doing the same for a bespoke app. Encouraging (or at least not preventing) sub-classing is OK for the former situation; it's not so good for the latter, not as a general philosophy it's not. With a custom app you'd better have it spelled out in your design in B&W exactly where potential inheritance is called for, and specifically design it only where it's spec'ed out. AHS
From: Rhino on 17 Mar 2010 11:06
On Mar 16, 7:06 pm, markspace <nos...(a)nowhere.com> wrote: > Rhino wrote: > > Again, can you clarify this a bit? You don't necessarily need to write > > an example; just pointing to a document or tutorial that contains an > > example would be just fine. I'm not sure where to look for such a > > thing. > > A lot of what is being discussed here is based on patterns from a book > called "Effective Java" by Joshua Bloch. It's basically "design > patterns for Java" and it's very good. You should pick it up. Whether > you use its ideas or not is up to you, but I think it would extend your > understanding of Java quite a bit. > > The basics of the Factory pattern are: > > 1. A static method that is the Factory. > > 2. A private-ish class that is produced by the Factory method. > > public class StringUtils { > > private StringUtils() {} > > public StringUtils getInstance() { > return new StringUtils(); > } > > } > > That's the idea, the full pattern can be more complicated. The > reasoning behind it is that there are some things you can't do in a > constructor, so the method gives you a change to add additional code > after (or before) the constructor is invoked. It's basically an > additional layer of encapsulation on top of the constructor. You should > look at the Java API and notice that a lot of the new-ish classes use > this kind of Factory pattern. Calendar, for example, and some of the > new Collections, like EnumSet. I don't own a copy of Effective Java but I read the article from Dr. Dobbs Journal that someone else cited and read that. Curiously, Bloch says that this technique does not correspond exactly with the GoF Factory design pattern (first paragraph after the Boolean example) but perhaps that's nitpicking. In any case, I read Bloch's discussion of this technique and found a few different examples of the Factory design pattern as well but for the life of me, I'm still not clear on exactly what you are proposing for my specific case. The methods in my StringUtils class are all static now and I have made the two constructors private. I've created a static factory method along the lines you describe above. In fact, I've created two of them, one that takes a Locale as a parameter and one that uses the desfault Locale. The compiler is not complaining about what I've done, which is a one hurdle overcome. But I'm not clear yet on how to invoke this static factory method, which makes me wonder if I'm fully understanding what you're saying. Here's an excerpt of my code, showing the constructors and the static factory methods and a few relevant fields: ---------------------------------------------------- public class StringUtils { /** * An instance of a Msg Resource Bundle. */ private static ResourceBundle locMsg = null; /** * The MessageFormat being used by this class. */ private static MessageFormat msgFmt = new MessageFormat(""); // $NON-NLS-1$ /** * The locale used by this class. */ private static Locale locale = null; /** * This constructor creates an instance of the class that uses the default locale. */ private StringUtils() { locale = Locale.getDefault(); locMsg = LocalizationUtils.getResources(locale, MSG_PREFIX); msgFmt.setLocale(locale); } /** * This constructor creates an instance of the class that uses a specified locale. * * @param myLocale the locale that should be used by this instance of the class. */ private StringUtils(Locale myLocale) { locale = myLocale; locMsg = LocalizationUtils.getResources(locale, MSG_PREFIX); msgFmt.setLocale(locale); } /** * This is a static factory method. * */ public StringUtils getInstance() { return new StringUtils(); } /** * This is a static factory method. * * @param myLocale the Locale that should be used by this class. */ public StringUtils getInstance(Locale myLocale) { return new StringUtils(myLocale); } //Other methods omitted (all of them are static). } ------------------------------------------------------------------- Is this what you have in mind? If yes, how do I invoke StringUtils.getInstance()? I've tried this (from another class) in order to get an instance that uses the default Locale: StringUtils stringUtils = StringUtils.getInstance(); but it generates a compile error because it doesn't like the static reference to getInstance(). And this gives the exact same error: StringUtils stringUtils = new StringUtils.getInstance(); Can you (or anyone else reading this thread) kindly clarify what I've got wrong and how to correct it? -- Rhino |