I think the advantage of structural type systems is that they encourage you to create fine-grained interfaces oriented towards what the user of the interface needs, rather than what the implementer provides.
In a nominative type system you need a common dependency on the interface. In a structural type system that requirement is eliminated: you can build a loosely coupled system without needing to create that common library where you put all the interfaces. Each client can independently declare the interface it expects from a collaborator.
The disadvantage of structural type systems is that they match up classes to interfaces which may not really implement the correct contract. For example, if you have this interface:
public interface IBananaProvider
{
/// Returns a banana, never null.
Banana GetBanana();
}
then the following class will implicitly be considered to implement IBananaProvider
in a structural type system. However, the class violates the post condition that the returned banana is never null:
public class SomeBananaProvider
{
// returns a banana or null if we're all out
public Banana GetBanana()
{
if (bananas.Count > 0)
{
return bananas.RemoveLast();
}
else
{
return null;
}
}
}
This could be fixed if the contract was somehow specified formally and considered part of the type structure. I think things are moving in that direction, e.g. System.Diagnostics.Contracts in .NET 4.0.