2,513 reputation
411
bio website
location Illinois
age 44
visits member for 2 years, 5 months
seen 4 hours ago

Nov
18
comment Does this Decorator implementation violate the Liskov Substitution Principle?
@Jules: IMHO, the normal pattern for object creation should be to call a factory method which then constructs an instance of its own type, but there's no way of knowing whether SomeType.someMethod() returns a type which has any relation whatsoever to SomeType. It would be nice if there were a means of invoking a static method which would make clear that the return type is the class upon which it is being invoked (and, in .NET, if interfaces could sport such static methods).
Nov
18
comment Does this Decorator implementation violate the Liskov Substitution Principle?
@Jules: One annoyance I have in Java and .NET is that the only construct for creating objects requires that the code invoking it specify the exact type to be created. While there are some situations where it's nice that new Foo() is guaranteed to return a reference to an instance of Foo to which no reference previously existed, there are many times when it would be nice to have an expression that makes clear its result type but is non-specific as to whether its exact type will be Foo or a derivative, or--for immutable types--whether the object will necessarily be new.
Nov
18
comment Why didn't == operator string value comparison make it to Java?
@maaartinus: Care to chat? I agree with you that Java allows a number of things that IMHO should be forbidden; it also forbids some things which IMHO should be allowed. I wish languages would include more primitive types for each storage format, depending upon whether types should try to behave like abstract numbers or machine-representable quantities. Should a 32-bit floating-point declaration be viewed as saying "I want to hold an exact power-of-two fraction, or as "I want to hold a real number, but will tolerate float precision"?
Nov
18
comment Why didn't == operator string value comparison make it to Java?
...comparison based upon actual numerical value with either convert both operands to double, or else test if converting the first operand to float yields the second and converting the second to int yields the first. If Java doesn't accommodate special behaviors for mixed-type operators in cases like that, adding it for the less common reference-vs-primitive comparisons would seem less compelling.
Nov
18
comment Why didn't == operator string value comparison make it to Java?
@maaartinus: If == never tested reference equality, then it could sensibly perform a null-safe value-equality test. The fact that it does test reference equality, however, severely limits how it can handle mixed reference/value comparisons without inconsistency. Note also that Java is fixed on the notion that operators promote both operands to the same type, rather than yielding special behaviors based upon the combinations of types involved. For example, 16777217==16777216.0f returns true because it performs a lossy conversion of the first operand to float, while a...
Nov
17
comment Am I violating LSP if the condition can be checked?
Having the return from the aggregating method only return Iterable<T> would make it impossible to retrieve indices 1,000,001 and 1,000,002 without having to iterate through the million-item list. On the other hand, if it could expose a better interface to the caller, then it could expedite the parts of the operation that could be expedited.
Nov
17
comment Am I violating LSP if the condition can be checked?
A problem with defining separate interfaces is that it becomes much more difficult to wrap or aggregate things. For example, consider a method which is supposed to accept two instances of Iterable<T> and return an Iterable<T> that contains all the items in one followed by all the items in the other. Suppose such a method is given a 1,000,000-item List<Foo> and an Iterable<Foo> that doesn't support anything other than basic iteration, and code which receives the return from the method wants items at indices 1,000,001 and 1,000,002.
Nov
17
comment Why would Square inheriting from Rectangle be problematic if we override the SetWidth and SetHeight methods?
If shapes objects are immutable, then one could have an IShape type which includes a bounding box, and can be drawn, scaled, and serialized, and have a IPolygon subtype with a method to report the number of vertices and a method to return an IEnumerable<Point>. One could then have IQuadrilateral subtype which derives from IPolygon, IRhombus and IRectangle, derive from that, and ISquare derive from IRhombus and IRectangle. Mutability would throws everything out the window, and multiple inheritance doesn't work with classes, but I think it's fine with immutable interfaces.
Nov
17
comment How to verify the Liskov substitution principle in an inheritance hierarchy?
...a shape with the specified height, and WithWidth that would return a shape with the specified width, if invoking those methods upon an ImmutableSquare could return an instance of ImmutableRectangle [it would also be possible that calling WidthHeight on an ImmutableRectangle whose width matched the passed-in value could return an instance of ImmutableSquare].
Nov
17
comment How to verify the Liskov substitution principle in an inheritance hierarchy?
@Songo: By my understanding of a "history" constraint, that would be violated if Square had been the base class with Height and Width (perhaps both derived from an abstract ReadableShape) that were tied together, and Rectangle was a derived class which allowed the creation of an instance where their values differed. Otherwise, I think Square simply violates the contract which says that setting Height should not affect width nor vice versa. Note that ImmutableSquare could inherit from ImmutableRectangle even if the latter contained a WithHeight method that would return...
Nov
17
answered Use cases for “private” interfaces?
Nov
17
answered Does this Decorator implementation violate the Liskov Substitution Principle?
Nov
17
comment Why didn't == operator string value comparison make it to Java?
...since autoboxing the int and doing a reference comparison would have been silly [but wouldn't always fail]. Otherwise, I see no reason to allow an implicit conversion that can fail with an NPE.
Nov
17
comment Why didn't == operator string value comparison make it to Java?
@maaartinus: A good language design should use separate equality operators for value and reference equality. While I agree that conceptually it would have been possible to have an int==Integer operator return false if the Integer is null, and otherwise compare values, that approach would have been unlike the behavior of == in all other circumstances, where it unconditionally coerces both operands to the same type before comparing them. Personally I wonder if auto-unboxing was put in place in an effort to allow int==Integer to have a behavior that wasn't nonsensical...
Nov
15
comment What is the difference between the factory pattern and abstract factory?
@DonalFellows: I wonder if there would have been any fundamental problems in Java or .NET with having a special syntax for invoking private constructors (e.g. new this(args), and having new className(args) invoke a static method className.ctor(args) [which for most classes could be auto-generated to simply return new this(args)]? I would think that would simplify the frameworks, and would also allow a constructor of class T to distinguish easily whether it was being used to construct a T, or prepare the base of something derived from T.
Nov
13
comment Is naming a class based on its implementation acceptable?
...read-by-index requests gets too great, then apply all pending operations at once). Many consumers of List would be happy with such an implementation, but a few might not. If code could indicate "in advance" whether such new implementations would be desirable, that would be helpful. Even with regard to things like concurrency, having a factory method which accepted a "requirements" parameter could be nicer than having a variety of collection types that would fit different needs, and would allow framework authors to develop more specific types when a need for them was demonstrated.
Nov
13
comment Is naming a class based on its implementation acceptable?
Having factory methods for such purposes is fine. My point was that most consumers of things like ArrayList don't really care whether or not all items are allocated in a single contiguous array, but some might; having code only use type ArrayList when it cares about such things would allow framework authors to do things differently (e.g. a List implementation could keep a queue of pending insert or delete requests, and handle read-by-index requests by adjusting the index based upon those pending requests; when enough items are added or deleted, or the cost of adjusting...
Nov
12
comment Is naming a class based on its implementation acceptable?
Clients which rely upon the internal design of a class should make instances using the constructor of the exact class they want, but clients who aren't going to be concerned about the design internals should create instances in a way which would allow the framework to substitute a different class whose internals are different but whose external behavior remains the same.
Nov
12
comment Is naming a class based on its implementation acceptable?
IMHO, code should endeavor to specify what it needs, and leave open things it doesn't care about; good languages should facilitate that. If a future version of a framework comes up with an improved "general-purpose" implementation of a base class or interface which has a different internal design, but will work interchangeably with the old one in any code which doesn't use Reflection or serialization, replacing the old implementation with a new implementation of the same class would break things, but having a factory method return the new type shouldn't break any properly-written clients.
Nov
10
comment When is type testing OK?
Except in scenarios where a type might need to hold one of two completely different things at different times and the requirements are clearly mutually exclusive (and thus using separate fields would be redundant), I generally consider a need for try-casting to be a sign that members which should have been part of a base interface, weren't. That's not to say that code which uses an interface that should have included some members but doesn't shouldn't use try-casting to work around the base interface's omission, but those writing base interfaces should minimize clients' need to try-cast.