4

Today im working in WPF.

I tried to inherit from System.Windows.Shapes.Line class, like this:

class MyLine : System.Windows.Shapes.Line
{
    public Ln()
    {
        this.Stroke = Brushes.Black;
    }
}

I just realized, that Line class is sealed.

My goal is to create a class, that will work like Line class (to put it on Canvas), but I don't want to mess my code with adding brush to it everytime, lets say always want black brush/stroke with 2px width.

I feel im trying to do it wrong.

How should I do that?

Kamil
  • 13,363
  • 24
  • 88
  • 183
  • 7
    use composition instead of inheritance? – Mathieu Guindon May 25 '13 at 01:10
  • @retailcoder Can you write some example? – Kamil May 25 '13 at 01:11
  • 1
    Why not instantiate a line instance and set the color? If you want it common wrap it in a static factory helper or something – devshorts May 25 '13 at 01:12
  • 1
    @devshorts I like the factory helper work-around - create a class, like, `LineFactory` that exposes a method which returns a `Line` that's configured as specified by the factory method's parameters. – Mathieu Guindon May 25 '13 at 01:14
  • @retailcoder now finally I understood what class factory is... And composition is just putting Line class inside my MyLine class? I think I got it. Btw. Shall I delete question, or someone will write answer? – Kamil May 25 '13 at 01:19

2 Answers2

4

You could create a factory class:

public class LineFactory
{
    public Line Create(<parameters here>)
    {
        //create and return a Line object
    }
}

The factory could also be static, but that could hinder testability.

Note that this solution doesn't let you extend the Line class as inheritance would. To do that you would need to return a MyLine class which would embed a Line object along with the additional properties you'd want MyLine to have.

public class MyLine
{
    private Line _theBoringOriginal; // composition: "has-a" (vs inheritance "is-a")
    public MyLine(Line line)
    {
        _theBoringOriginal = line;
    }

    public foo SomeProperty { get; set; }
}

If it's just methods you want to extend the Line class with, you don't need a new class, you could just write extension methods in a static class:

public static foo DoSomethingCool(this Line line, <parameters here>)
{
    // whatever
}
Mathieu Guindon
  • 69,817
  • 8
  • 107
  • 235
  • 1
    Static classes are ok (from a testing standpoint) as long as they themselves are under test and do not rely on external dependencies. – Justin Pihony May 25 '13 at 01:23
  • @JustinPihony I see, you can't constructor-inject dependencies in a static (no instance) class! Thing is, it's likely that the factory class will be some other SUT's dependency and *that* would/could be problematic, no? I'm a little green on testing and read everywhere that `static` is a big no-no for that, so I just steer away from anything static. – Mathieu Guindon May 25 '13 at 01:30
  • It would not be problematic as long as it is a deterministic method with no side effects and the method is under test. Something like `Math.Round` As a note, the static File methods are bad since they are dependent on the file system – Justin Pihony May 25 '13 at 20:02
3

Why not simply create an extension class to do what you want? Extension classes were create specifically to allow you to extend sealed classes with new methods, without having to actually inherit things.

public static class LineExtensions {
    // returns the Line so you can use it fluently
    public static Line MakeLineBlack(this Line line) {
        line.Stroke = Brushes.Black;
        return line;
    }
}

Then you can just do this:

var line = new Line().MakeLineBlack();
Erik Funkenbusch
  • 92,674
  • 28
  • 195
  • 291
  • The problem with this approach, is that you end up with chained calls that end up being nothing more than micro-configuring your line through static method calls which *could* end up looking like this: `line.MakeLineBlack().MakeLineDoubleDashDot().MakeLineHeavyWeight().MakeLineBlue().OopsThoughtItWasBlack().MakeLineDoubleDashDot().OopsAlreadySaidThat()....` - vs a factory method that simply creates what is says it creates (e.g. `CreateBlackDoubleDashDotHeavyWeightLine()`) and does it in a single call. Not sure *when* or *why* going down the static road could be an *absolute* necessity. – Mathieu Guindon May 25 '13 at 02:37
  • @retailcoder - It's more a preference than anything else. Using fluent methods, I can mix-and-match without writing additional code, with your approach you have to write a new method if you want CreateBlackHeavyWeightLine(), I simply have to call Line.Black().HeavyWeight() – Erik Funkenbusch May 25 '13 at 05:14
  • I'd prefer `PaintIt (Black)` over `Black ()` because otherwise the fluent syntax doesn't add much to just directly setting the property, and having a static class with methods to set every possible value of every settable property, smells like YAGNI to me (if you're not going to need a new ext.method it means you already wrote it). – Mathieu Guindon May 25 '13 at 14:00