Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add shadow classes as a way to extend sealed classes. #204

Open
ghost opened this issue Nov 26, 2017 · 8 comments
Open

Add shadow classes as a way to extend sealed classes. #204

ghost opened this issue Nov 26, 2017 · 8 comments
Labels

Comments

@ghost
Copy link

ghost commented Nov 26, 2017

We have a way to re-implement non-overridable (sealed) methods, fields and properties using the Shadows keyword.
But on class-level we do not have a way to override non-inheritable (sealed) classes.

I'd like to see the Shadow keyword for inheritance too, making the following syntax valid:
Public Class MyClass
Inherits Shadows System.String
End Class

The inherited class should 100% act like system.string, but with the possibility to reimplement (shadow) all public members.

An example of the internal representation of the shadowed class can be seen with the extension "ShadowClasses" (link: https://marketplace.visualstudio.com/items?itemName=theoverweij.ShadowClasses-Extension-For-VB )

@reduckted
Copy link
Contributor

How would this be helpful?

@ghost
Copy link
Author

ghost commented Nov 27, 2017

A lot of the classes in the .Net framework are sealed making it impossible to extend them.
If I need an extended implementation of a sealed class, the only thing I can do at this moment is reimplement almost everything instead of changing one or two items in the class.

@reduckted
Copy link
Contributor

Can you provide an example of where this would be useful?

@ghost
Copy link
Author

ghost commented Nov 27, 2017

@reduckted
By example: make a FixedLengthString class that is 100% compatible with String

It's absolutely not daily routine, but sometimes I need a change in an existing framework class, and then I find that the class is sealed, so I am ending up in the complete re-implementation of the class instead of inheriting and make the change. With the cost of a few days of work instead of a few minutes,

@AnthonyDGreen
Copy link
Contributor

In the string case you provide, isn't a problem that no methods anywhere which take a String would be able to take your FixedLengthString? Since this would not be true inheritance, none of the polymorphism stuff would actually work. And if the type you're shadowing has a base type... that type hierarchy won't be preserved in the shadow. Is this not a problem?

@ghost
Copy link
Author

ghost commented Dec 1, 2017

In the string case you provide, isn't a problem that no methods anywhere which take a String would be able to take your FixedLengthString?

This is solved by the auto-generation of the widening and narrowing operators, so it will using option strict off. If option strict is on, you can use the .base property.

The type hierarchy is preserved as much as possible because the shadowed class uses the same base class as the class that is shadowed.

Example of the extra code needed in the generated class:

Public Class Shadowed_System_String
    Inherits System.Object 'the base class of the base class
    Implements <all interfaces that the base class implements>

    'Generated shadow class of System.String
    Private WithEvents pBase As System.String
    Public Overridable Property Base As System.String
        Get
            Return pBase
        End Get
        Set(value As System.String)
            pBase = value
        End Set
    End Property

    'All public contructors of the base class
    '+ 1 extra contructor to create the shadowclass with an instance of the baseclass
    Public Sub New(base As System.String)
        pBase = base
    End Sub

    'All public events of the base class + nonpublic events needed to implement one of the interfaces
    'by example:
    'Public Event x(sender as Object, e as EventArgs)
    'Public Sub Handler_x(sender as Object, e as EventArgs) Handles pBase.x
    '    RaiseEvent x(sender, e)
    'End Sub

    'All public properties of the base class + nonpublic properties needed to implement one of the interfaces

    'All Methods of the base class + nonpublic methods needed to implement one of the interfaces

    'All operators of the baseclass, translated to the shadowed class
    'example Public Shared Operator =(a As String, b As String) As System.Boolean
    'becomes: Public Shared Operator =(a As Shadowed_System_String, b As Shadowed_System_String) As System.Boolean

    'extra narrowing and widening operators to convert between the baseclass and the shadowclass
    Public Shared Narrowing Operator CType(bs As Shadowed_System_String) As System.String
        Return bs.Base
    End Operator
    Public Shared Widening Operator CType(bs As System.String) As Shadowed_System_String
        Return New Shadowed_System_String(bs)
    End Operator
End Class

About polymorphic - it would not work, just like it will not work for shadowed methods in in normal inherited classes.

@ghost
Copy link
Author

ghost commented Dec 1, 2017

deleted this comment

@ghost
Copy link
Author

ghost commented Feb 16, 2018

How would this be helpful?

It enables me to extend sealed classes that I otherwise have to build from the ground up

Can you give an example where this could be usefull?

In any case that you need a specialized version of a sealed class

Other possible questions:
Why do you want to inherit a sealed class?
Return question as answer: Why did you seal it in the first place?
Answer to that question: because of performance.
remark on that answer: I understand that, but I want flexibility and the possibility to use OOP.
Following question: but a shadow class is not real OOP ...
Answer: No it isn't, but is is just as flexible as shadowing a non-overridable member in a non sealed class; a shadowed class is just a class that shadows all public members (and default calls the original implementation) . Not the most desirable situation, but the best that is possible. And it prevents complete new implementations of a class where a few lines of code are enough to reach the desired results.

@ghost ghost closed this as completed Mar 6, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants