Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Is it a fair assumption to say that an overloaded constructor for a class can be thought of as a 'duck' for duck typing? Let's say that ClassA has an overloaded constructor, it would stand to reason that the different constructors are there for a reason -- the object is being used in a manner that indicates all of its properties do not have to be set for the object to perform correctly.

So, I ask, is an overloaded constructor a duck?

share|improve this question

3 Answers 3

up vote 10 down vote accepted

No, It Isn't Duck Typing

I would argue that this is not an acceptable form of duck typing in a static language.

In a language that supports duck typing, one would expect to be able to define a function that accepts an object foo of unspecified type that defines a function (or property) bar.

def call_bar (foo) {
  foo.bar
}

The function doesn't care what type foo is, just that is defines bar. Your system doesn't provide any way for a function to take an object of any type, so long as that type defines the required functions.

So how could we get duck typing in a statically typed language?

1. Interfaces

Well, the typical approach in most languages is to define interfaces. This doesn't get us all the way there, but it gets us close. We can at least define a contract by which we identify any pertinent functions/properties/etc on a type.

A function can then be written so that it accepts inputs by interface, rather than concrete classes. We retain the ability to check the type at compile time, to ensure that the required functions exist on the inputs, while getting the flexibility to ignore the implementation details.

2. Structural Typing

Scala has an interesting approach to this, which offers a much more flexible way of getting duck-typed behavior in a static language. Scala allows you to reference a type in terms of its members, using the following syntax:

def callBar(foo : { def bar() : Unit }) = {
  foo.bar()
}

This will match any types that define the bar function, accepting no inputs and returning void output. You also retain the static typechecking benefits of a static language, as opposed to relying on late-binding to determine whether or not inputs will have the right members.

share|improve this answer
    
Good explanation, + 1 –  wootscootinboogie Jul 22 at 21:00
2  
+1 for Structural Typing. This is also how Standard ML, OCaml, Haskell, and I imagine F# as well handle the issue. C++ templates are also a form of structural typing, except it's implicit and blows up with really ugly compiler errors when you get it wrong. –  Doval Jul 22 at 21:19
    
@Doval: Haskell’s type classes are a bit different, since they require that the type in question be declared an instance of the class elsewhere, whereas Scala’s structural subtyping is fully ad hoc. –  Jon Purdy Jul 22 at 21:44
    
@JonPurdy True, but in practice I doubt there's much of a difference. If the concept "has bar()" is useful, you'll likely want to give it a name to refer to it more easily, especially since you need to document the semantics somewhere. In any case I feel the important characteristic is that either mechanism will let you say "I'm expecting something with the following members" after the fact, as opposed to interfaces which must be anticipated and implemented up front. –  Doval Jul 22 at 22:04

No it isn't.

Objects of a particular class all support exactly the same set of messages no matter what constructor they were created with. Overloading constructors merely means that it isn't necessary to initialize explicitly all the fields that make up an object's state. For instance, an object might have color with a sensible default value, so you can have a constructor with a color value and one without such a value, while a field that is an obligatory foreign key to another entity can't be made up by the class, so it always has to be a constructor argument. But in Java, all class members are fully defined when an object is constructed (in fact, at run-time there is no such thing as an undefined value), so comparing Java objects to those in duck-typed languages isn't helpful.

share|improve this answer

It's fair to say that overloaded constructors specify different ways to construct a duck. That's not duck typing, though.

Consider the following class:

public class Rectangle
{
    public Rectangle(Point A, Point B)
    {
        // Constructs a rectangle by using points A and B as a diagonal,
        // and filling in the rectangle with the usual lines at right angles.
    }

    public Rectangle(Point A, Length diagonal, Angle angle)
    {
        // Computes Point B using the specified size and diagonal, and then
        // calls the first constructor.
    }

    public Rectangle(Point A, Point B, Point C, Point D)
    {
        // Constructs a rectangle from the four supplied points, and 
        // verifies that all angles are 90 degrees.
    }
}
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.