Partial Classes in DWScript

Support for partial classes has been added to DWScript: they can be declared as “class partial (TAncestor)” as well as with the Oxygene syntaxpartial class (TAncestor)” syntax.

Partial classes allow to split the definition and implementation of a class over multiple files, or over multiple sections of the same file. Partial declarations must have the same modifiers (abstract, sealed, static…), must specify the same ancestor (or none), however each partial declaration is allowed to introduce new interfaces and their implementations.

Partial class can have multiple purposes, to quote wikipedia:

  • Facilitates the implementation of code generators that have to “inject” code declarations/implementations that comes form other descriptions, such as a Visual UI designer, data and string resources, etc.
  • Enables separation of concerns, in a way similar to aspect-oriented programming but without using any extra tools.
  • Enables optionally composited functionality, which can be omitted or substituted depending on target or requirements..
  • Enables separation of a class’s interface and implementation code in a unique way. (irrelevant for Pascal!)
  • Enables multiple developers to work on a single class concurrently without the need to merge individual code into one file at a later time.
  • Eases navigation through large classes within a editor.

 

5 thoughts on “Partial Classes in DWScript

  1. Stefan Glienke :
    Wow! I wonder when you will add full AOP support to DWS

    Partial classes were a low-hanging fruit, actually, at some point all class were partial “courtesy” of a compiler bug 😉
    That said, before AOP, there are attributes, generalized “set of” & templates in the pipe, along with probably a myriad of loose bits, ends, and minor features!

  2. Ouch! I really don’t see this as a good or useful feature. Let’s see here:

    > Facilitates the implementation of code generators that have to “inject” code declarations/implementations that comes form other descriptions, such as a Visual UI designer, data and string resources, etc.

    Yeah, this is why .NET has partial classes. Instead of using a form-definition language like Delphi, they added all sorts of unnecessary complications and difficulties to Winforms by doing the whole thing in code. (I can’t help but wonder if part of the motivation for XAML didn’t come from them finally realizing what we had known all along: that that’s a horrible way to set up forms.)

    > Enables separation of concerns, in a way similar to aspect-oriented programming but without using any extra tools.

    If you’re trying to separate concerns, why are you putting them together in the same class?

    > Enables optionally composited functionality, which can be omitted or substituted depending on target or requirements..

    …which can be done just as easily with IFDEFs, which has the further advantage of making your intentions explicit.

    > Enables separation of a class’s interface and implementation code in a unique way.

    “Unique” unless you mean “the same as how C and C++ do it,” which is a horrible model. There’s a good reason why .h files don’t show up in other languages.

    > Enables multiple developers to work on a single class concurrently without the need to merge individual code into one file at a later time.

    Enables multiple developers to develop parts of a class independently, with no coordination, so you end up with a mess of a class whose parts don’t work together well. (And wouldn’t a class big enough to be broken up this way violate SRP anyway?)

    >Eases navigation through large classes within a editor.

    …huh? How do you make navigation easier by giving it more files to lookup and keep track of?

  3. Mason Wheeler :

    …which can be done just as easily with IFDEFs, which has the further advantage of making your intentions explicit.

    I’m not a fan of IFDEFs, since they mingle optional or platform-specific code with regular code, they are often a PITA to deal with in greater code-bases, and you need to run multiple builds with all the various IFDEF conditionals to check everything.

    If you composite with partial classes, then you get compile-time checks with a single-build, and you can segregate optional functionality to optional files in a much cleaner way than using IFDEF/INCLUDES (especially since with IFDEF/INCLUDES, you would need one file for the declaration, another for the implementation, like in C).

    For instance in Delphi that means you could have optional LiveBinding capability for components, without having forced LiveBinding dependencies even if you don’t need them.

    As for dynamic/RTTI description, I’m of two minds there: on one side having a separate DFM/XML is convenient, on the other, it means you end up with RTTI and runtime errors, where you could have had static typing and compile time errors, ie. the flexibility you get comes at a stability price. And refactoring code with compiler support is simple, refactoring resources DFM/XML isn’t.

    Enables separation of a class’s interface and implementation code in a unique way.

    Good point, this one was copy-pasted and is irrelevant to Pascal, I’ll scratch it from the list.

    And wouldn’t a class big enough to be broken up this way violate SRP anyway?

    Sometimes, classes just have to be big to be practical IME (of course that shouldn’t be abused), or you end up with overcomplicated architectures or “public everything”.
    Think of TComponent, and other base classes that introduce support for multiple interfaces.

    Partial classes can turn especially useful for interfaces, as you can segregate the interface declaration & implementation in another, optional unit.

    …huh? How do you make navigation easier by giving it more files to lookup and keep track of?

    By making the file focused on one aspect, f.i. if you use the partial class to implement an IPrintable interface, or an IDragDropAble, etc. You’ll have a bunch of related methods that extend the class, and are intrinsically optional, and exchangeable.

    F.i. even if you don’t like the Delphi LiveBinding implementation, you’ll have to deal with it, or at least carry it around as RTTI dead weight. If it had been made into a partial class, you could have avoided it if you were not using it, or replaced it with some different design/implementation.

  4. @Eric

    To be useful, partial classes should fit dev model and “source architecture” for development. Your disagree with Mason is based on different ways for development. Delphi for long time did not support partial classes, so there is a little adopting for this feature. So dev model for Pascal-based development did not have good and practical examples for parital class’s usage. But partial classes can be useful, and you pointed some good ways to use them (interface support, IMHO).

Comments are closed.