Repository navigation
Proposal for Abstract Classes and Methods #3578
Description
Activity
- addedSuggestionAn idea for TypeScriptAn idea for TypeScriptIn DiscussionNot yet reached consensusNot yet reached consensus
on Jun 19, 2015 Thanks for that!
Moreover, the assignability of abstract types is restricted to instances that are abstract
I do not understand what you mean by this.
- Increases the complexity of the language.
Pretty much how I feel about it. I'd rather see a more lean functional-like TypeScript then adding astronaut like OO patterns like abstract or decorators.
This overlaps tons with mixins or traits too (combining things from other things). The benefit of traits or mixins is you can design 'abstract patterns' that work with modules too. This proposal is limited to a 'class' which lets face it is really a function under the hood.
Mohamed Hegazy (@mhegazy) This definitely needs re-wording.
We want to prevent the constructor of an abstract class from being invoked. So we wanted to restrict the assignability of the constructor function. Consider the following example:
class A {} abstract class B extends A {} var BB: typeof B = B; var AA: typeof A = BB; new AA;
We don't want the second assignment to be legal. So we restrict the assignabilty of objects whose type is the type of an abstract class to other objects whose type is the type of an abstract class.
I haven't yet implemented this as part of the attached PR.
I've updated the spec to clarify this.
Jon (@jbondc) so true, inheritance (for the sake of code "reuse" or whatever else) is a hands down rotten idea, composition does it all with a little bit more effort, screw this s*t
👍
💩 I'd love to hear how this aligns with the design goals:
5. Produce a language that is composable and easy to reason about. 6. Align with current and future ECMAScript proposals. Non-goals 1. Exactly mimic the design of existing languages. Instead, use the behavior of JavaScript and the intentions of program authors as a guide for what makes the most sense in the language.I have long argued of the merits of embracing the protypical nature of ECMAScript instead of projecting a traditional OO paradigm. On the other hand, that hasn't stopped the wider community rejecting that and ECMAScript has taken a large bend towards traditional OO with ES6, though there seems much debate on this, as several of our ECMAScript luminaries seems to be conflicted on every aspect of this.
Jon (@jbondc) I think it is a fair challenge to question this proposal in line with design goals 5 and 6. It is very likely that some sort of abstract/traits/composition type features will end up in ES, though there seems to be no common consensus. Both abstract and traits were proposed during the class discussions in ES6/2015, but all got dropped because no one could agree. TypeScript already has interfaces which provide a sufficient level of abstraction ahead of any implementation of something along this line of ES.
The traits discussion (#311) was closed by Ryan Cavanaugh (@RyanCavanaugh) because of this conflicting with goal 6. I quote:
There's a lot of overlap here with mix-ins; it would be bad (or at least treacherous) to do both. With mix-ins being a potential part of ES7/ES8+, we want to take the runtime side of this very conservatively and get TC39 to agree on a proposal in this area first.
I honestly don't see what the difference is here.
Jon (@jbondc) so true, inheritance (for the sake of code "reuse" or whatever else) is a hands down rotten idea, composition does it all with a little bit more effort, screw this s*t
While I am personally a fan of compostability, a strong emotive response without well thought arguments is unlikely to further your thoughts, especially when it appears you want to throw your arms up in the air and walk away. I don't think that is your intent, but that is the way it comes across.
Here is the statement: inheritance is a dangerous tool that causes more problems than solves
- it takes knowledge, practice and discipline to use it right (which junior/mid developers generally lack)
- it takes experience to grasp the understanding where it may NOT be used
- yet, given all of above, even experienced developers with well designed systems fall short when requirements change and it comes to redesign and it turns out that existing inheritance hierarchies are too rigid to change
All this contributes to frustration, missed deadlines, and myths that coding is hard. In my experience nothing is hard if designed properly. Well, inheritance encourages bad design by allowing developers to violate:
- (open closed principle)[https://en.wikipedia.org/wiki/Open/closed_principle]
- (Liskov substitution principle)[https://en.wikipedia.org/wiki/Liskov_substitution_principle]
Besides that
- having to choose one single super-class among a few possible others inevitably favoring one predecessor over all equally important others, resulting to skewed hierarchies
- in a sub-class, having to comply to the interface of the super-class even though it goes against the needs
- leaving a class unclosed and allowing uncontrolled sub-classing that wasn't intended
Besides that, there is quite a number of successful examples of languages without inheritance at all:
- (COM)[https://www.microsoft.com/com/default.mspx] where code reuse is achieved with interface inheritance and composition only
- functional lanaguges where code reuse is achieved by various means (parametrizing with functions, typeclasses, class modules) without having to alter the existing code
DanielRosenwasser commented
on Jun 25, 2015 MemberMore actionsAlright, while we'd love to have a constructive conversation on the merits of different approaches in software design, I believe that classes are a useful abstraction and the
abstractmodifier would bring utility. For those who prefer using this paradigm, it would surely be helpful.Unless there are specific "gotchas" introduced in our language from
abstractthat are not found in other languages, I disagree that users would find this extremely complex. If one understands classes and one understands interfaces, then abstract classes do not require a massive cognitive leap.Objective thinking:
http://ocw.kfupm.edu.sa/ocw_courses/phase3/ICS201-Offering-052/Readings/p123-armstrong.pdfWhat bothers me the most is the increasing and consistent sidestepping of the 'TS design rules' in favor of:
- Whatever aligns with the Microsoft Way does not require any justification
Kitson Kelly (@kitsonk) I must have missed it, when was abstract ever proposed?
http://wiki.ecmascript.org/doku.php?id=strawman:oldes626 remaining items
Aleksey-Bykov C# operates under a completely different set of constraints than TypeScript does. We could love pure functional programming more than anyone but it doesn't change the rules we actually need to operate with as we design for the future (ie conforming to future ECMAScript standards). If you want an arbitrary set of language features/semantics that compile to JS there are a lot of options, but TypeScript isn't one of them. There are also web centric languages that have opted to add desirable expression level features divorced from ECMAScript standards. The value/success of these two divergent strategies is left as an exercise for the reader ;)
Suffice to say, we love designing new language features and want to keep adding stuff that makes everyone's lives easier, but it's simply not the case that we get to just pick our favorite features from Haskell, Smalltalk, etc and put them into TypeScript with no regard for future ECMAScript incompatibility they may/will cause.
Great job!
Just one question: it seems that properties cannot be abstract.
The codepublic abstract get myProp(): string;is not accepted.
Limitation or bug?Yves Marx (@Yves57) this is by design. there is no way to currently to distinguish between a property accessor and a property declaration, so a derived class can define a property declaration and would meet abstract constraints, but probably this is not what you intended by making the accessor abstract in the base.
Mohamed Hegazy (@mhegazy) To be more precise, my case is the following
interface IMyInterface { myProp: string; } abstract class MyBase implements IMyInterface { abstract get myProp(): string; ......... }But I understand that this is a specific case!
Yves Marx (@Yves57), I've faced exactly same problem. Looks like this case isn't so rare...
It would be better if abstract class was allowed to miss fields from it's interface (both value properties and methods), like in other OOP languages.
So, this should be allowed:interface A { p; m(); } abstract class B implements A {} class C extends B { get p() {...}; set p(v) {...}; m() {...} }
But currently it gives:
Error:(2, 16) TS2420: Class 'B' incorrectly implements interface 'A'. Property 'p' is missing in type 'B'.
Also I think that abstract value properties should be allowed in abstract classes (same way value properties are now allowed in interfaces):
abstract class A { abstract p; } class B extends A { get p() {...} set p(v) {...} }
Denis Nedelyaev (@denvned) can you file separate issues to track the two requests, 1. abstract properties, and 2. missing property declaration in abstract class implementing interfaces.
I'm trying to use this in WebStorm 11 with TS1.6... Not working?
DanielRosenwasser commented
on Nov 3, 2015 MemberMore actionselectricessence WebStorm doesn't use our language service, so unless this is an issue you're seeing at compilations (i.e. not while editing) you should probably check in with them.
Though, it looks like they should support it: http://blog.jetbrains.com/webstorm/2015/09/webstorm-11-eap-142-4723/
AJamesPhillips commented
on Dec 8, 2015 More actionsBryan Rayner (@bryanerayner) +1 for:
Aleksey-Bykov, I'd actually love to have mixins as a feature, but can't comprehend doing it without structured type support.
Have you started submitting a proposal for mixins with typescript? If you haven't, are there good references to prior work where someone might begin working on fleshing that out?
AJamesPhillips commented
on Dec 8, 2015 More actionsAleksey-Bykov agreed, I shouldn't have said mixins as practically they share major downsides with multiple inheritance. For the moment I'm:
- making sure my inheritance trees are as shallow as possible
- using the is-a guideline
- utility functions
- And when all that fails because you have multiple base classes something "must" inherit from (and which utility functions can't deal with elegantly) then public and or private attributes set to helper functions and or class instances. If the helper functions and or class instances also need a reference to the instance then I set them in the constructor and pass
thisto them then.
Would be very interested to see composition / stamps / aspect / traits, in TypeScript. And thanks for the link to Dan Abramov's article.
It works in 11.
From: Daniel Rosenwasser [mailto:notifications@github.com]
Sent: Tuesday, November 03, 2015 3:44 PM
To: Microsoft/TypeScript
Cc: electricessence
Subject: Re: [TypeScript] Proposal for Abstract Classes and Methods (#3578)electricessence https://github.com/electricessence WebStorm doesn't use our language service, so unless this is an issue you're seeing at compilations (i.e. not while editing) you should probably check in with them.
Though, it looks like they should support it: http://blog.jetbrains.com/webstorm/2015/09/webstorm-11-eap-142-4723/
—
Reply to this email directly or view it on GitHub #3578 (comment) .Image removed by sender.- locked and limited conversation to collaborators
on Jun 19, 2018
Proposal for Keyword
abstractThis is a proposal for a new keyword,
abstract, to allow for incomplete/partially implemented classes.Introduction
This proposal expands upon #6, #2946, #2947.
Consider the following situation. A user would like to create a base class that shouldn't be instantiated as a template for derived classes. S/he might write something like
Today, the writer is forced to make a choice: either (i) Animal can be declared an interface, but then
yearsLeftcannot have an implementation, or (ii) write the program as above, but then Animal can be instantiated andmakeSoundhas a bogus implementation! Neither of these options is particularly attractive.We propose
abstractas a class declaration modifier to allow the programmer control over whether a class can be instantiated, and as a member function modifier to control whether said member function offers an implementation (and whether the enclosing class is abstract).Details
The modifier
abstractcan prepend a class declaration or a member function declaration. Constructors cannot be declared abstract.typeof CwhereCis anabstract-declared class (hereafter abstract class) cannot be instantiated via calls tonew.abstractdoes not have an implementation.super.foo()wherefoois an abstract method belonging to the parent class.this.foo()wherefoois an abstract method belonging to that class.abstractandstatic.abstractandprivate.abstractkeyword.The following code snippet summarizes valid and invalid usages of the
abstractkeywordPros
abstractannotations clarify the role of base classes in various patterns.Cons
To Be Discussed
Proposed Changes to Grammar
A.6 Classes
ClassDeclaration:
abstractopt class Identifier TypeParametersopt ClassHeritage { ClassBody }
MemberFunctionDeclaration:
MemberFunctionOverloadsopt MemberFunctionImplementation
AbstractMemberFunctionOverloads
AbstractMemberFunctionOverloads:
AbstractMemberFunctionOverload
AbstractMemberFunctionOverloads AbstractMemberFunctionOverload
AbstractMemberFunctionOverload:
AccessibilityModifieropt abstract PropertyName CallSignature ;
A.10 Ambients
AmbientClassDeclaration:
abstractopt class Identifier TypeParametersopt ClassHeritage { AmbientClassBody }
AbstractOrStatic:
abstract
static
AmbientPropertyMemberDeclaration:
AccessibilityModifieropt AbstractOrStaticopt PropertyName CallSignature ;
EDIT: updated to clarify the assignability of objects of "abstract type".