Yes, SpecialTable
can be produced by the same factory (and by the same factory method) that produces Table
. This not a problem, as long as SpecialTable
provides at least the methods guaranteed by the Table
interface (which it does).
This sort of situation makes sense when objects returned from the factory have some guaranteed behaviour/functionality (interface Table
), and some optional stuff (interface SpecialTable
).
So, in order to make use of the optional extra abilities/stuff available on some concrete objects returned by the factory, you have a few choices:
use polymorphism (recommended)
make use of instanceof
(or similar), which can be used to check for interface compliance/exact typing (avoid this if possible!)
Using polymorphism
An example to illustrate: suppose SpecialTable has extra data and an extra widget 'blarg' which appears on the UI representing special tables. Do you really need the code which uses SpecialTable to know that it needs to add 'blarg' to the UI? Or can you just have your external code ask the thing of type Table to add its necessary UI components to some UI container? Then the calling code doesn't care what exact type the thing is -- SpecialTable deals with it, adding the 'blarg' to the container itself. This pattern can be described as the delegate pattern (also sometimes also known as strategy pattern).
Using instanceof (type checking)
Example of instanceof
use:
// Table and SpecialTable are interfaces
Table table = TableFactory.instance().getDefaultTable();
if (table instanceof "SpecialTable") {
SpecialTable specialTable = (SpecialTable)table;
specialTable.specialMethod();
}
table.normalMethod();
Note that when you define your SpecialTable
interface you can declare it as extending the Table interface and then only list the extra methods.
Your factory will be producing concrete objects of either type. So you might have a concrete class called BoringTable
which implements Table
, and a concrete class called ExcitingTable
which implements SpecialTable
.
Beware instanceof!
It's generally better to avoid things like 'instanceof' (or generally speaking, ifs of any kind which depend on what type an object is). You should favour polymorphism instead. By this I mean having multiple different classes, of a common type, enclosing different behaviour in their implementation code.
Ask yourself this: does the class using something of type Table
(which might also be of type SpecialTable
) need to care if it's a special table or not? Can you not hide that distinction in some sort of implementation of the SpecialTable -- have it do something different, something extra, that plain old Table does?
Using strategy objects in the described way is a good start to simplify your PointBase
class, I would not hesitate to introduce them even if they do not solve your problem with the BreakEven
property.
For allowing custom properties, you could provide some kind "extension mechanism" in your PointBase
class (which I would rename to Point
after the redesign). In the most simple form, this could be just a list of custom properties for each Point
object, together with a list of their values (and the list is empty by default). This might boil down to some kind of EAV model. EAV is sometimes seen as an anti-pattern, but for this specific case its usage is fine as long as you do not use it for the majority of properties, only for your "special custom properties".
See also this former question on "Programmers" about custom fields. In my answer there, I mentioned Martin Fowler's book "Analysis Patterns" - I am pretty sure it will help you for your problem, since it contains a very extensive discussion how to model measurements and observations, including (custom) properties and similar things.
Best Answer
The explanations you quoted make sense from a semantical English point of view, but they are horribly ambiguous because it uses words that have very specific meaning in software development terms, but he's relying on the common English definition of these words.
This book was released 31 years ago and I suspect that it was ahead of what is now considered common OOP jargon, so the correctness of its words has changed because the world changed, not the book itself.
This book was revised 13 years later, and I suspect they may have modernized parts of the semantics (e.g. your third quote), but inconsistently so (e.g. not the first and second quote).
1
I believe he's talking about strong typing here, i.e. the fact that an object has a given type, which has a predetermined structure (i.e. an explicit class definition with methods, properties, ...) and that this structure is defined during design time (i.e. pre-compilation) but that the values stored inside are usually not known at design time, only during runtime.
What I suspect he is not talking about, but totally seems like he is at first sight, is static vs non-static properties.
If my interpretation is correct, then "state" here is not intended to mean "stored information" (as in: state vs behavior), but rather "structure of the class" (as in e.g.: the state of the union).
2
The same trend of using semantical English continues here.
By "static", just like before, he seems to mean "part of the class definition", not
static
specifically.By "property", it seems he means the common English word for "trait" or "characteristic", e.g. in the sentence "Each of these states of matter is characterized by different physical properties".
In more modern language, we would now say that accepting money is part of the contract of a vending machine.
This quote is not trying to distinguish properties from methods. It's saying that the ability to accept money needs to be part of a vending machine's public interface. The quote leaves it unspecified as to how this should be added to the class, but I do agree with you that this is obviously a method, not a class property.
3
And then here, it seems like we've suddenly switched to using specific developer jargon. If you forget the earlier quotes, this statement makes perfect sense, essentially explaining that state is stored in class properties (whether static or not).