-
Notifications
You must be signed in to change notification settings - Fork 58
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
Abstract classes #69
Abstract classes #69
Conversation
This will be annoying to handle in the parser, but I suppose there's no way around that. We had the same issue with
Hmm, that's interesting. I'm worried about confusing error messages here because this involves 3 different types (the abstract class, the interface and the implementation class). But if this is how it works in Java then I agree we should comply. |
Why not? I think default implementations can be quite useful, especially when an abstract class provides multiple methods defined in terms of the other methods. Then only providing an implementation for some is enough. |
You can just have a normal function which you'll override if you want an implementation, if I understand correctly. |
Ah indeed, the methods also have to be marked with |
I can live with abstract class syntax, but I would prefer abstract keyword to stay as compile time feature, while virtual keyword could better describe runtime feature, e.g. something which exists at runtime, but it is not real unless implemented. And that leads to another interesting thing: if abstract class implements interface, access to members of inherited classes could be a lot faster through abstract class than trough interface. And what about private constructor on abstract class? Will be allowed? Forcing super call on inherited classes? |
No special rules for constructors. That's why I didn't mention it. |
I like it. There is another alternative that I sometimes use (but I’ve always missed traits or abstract classes as it is described here):
Can you define Lastly for me the biggest problem is that future Haxe beginners will have a hard time figuring out what all these abstracts are. We already know the language so it’s not a big problem for us. ah one last question: Were you suggesting modifying current |
We already have |
On further thinking yes. I feel the reason I don't feel comfortable with all the variants is partly because historically it would have been more logical getting It also means, if in the documentation we introduce |
Updated with clarifications regarding constructors and static fields. |
If you don't mind, I have some questions:
abstract class Abstr {
public final value:String;
public function new(value:String) {
this.value = value;
}
public abstract function toString():Void;
} or abstract class Abstr {
public function sayHello() trace(toString());
public abstract function toString():Void;
}
|
I vote to accept. There's several places in the Haxe std lib where we rely on hacks to get around the lack of a proper abstract class. I think where we do this, the code feels awkward and fragile. Haxe contributors don't feel confident making changes since they don't understand the impact across all targets, and as a result the code becomes neglected. We really should fix it. I realize that we will have this weird semantics problem with "abstract" as a descriptor... it could be "abstract type", "abstract enum", or "abstract class", all of which are fundamentally different in potentially surprising ways. I think the notion of"abstract" should get a special section in the manual at the very least. Understanding the notion of "abstract" is key to exploiting the power of Haxe (probably more so even than macros), but I doubt many folks in the community clearly understand these concepts. I'll give more specific thoughts inline in other places, just wanted to give my top level thoughts here. |
Yes from me too. I'm very much looking forward to a cleaner standard library that doesn't have these |
For having common implementation mixed in abstract classes I think it's the core strength of abstract classes so it should be allowed, I wonder if any of our targets with abstract classes actually disallowed it.
One thing I've remembered: Is the |
We would not be overriding any implementation, so as a Haxe user it would bring confusion and inconvenience if we had to use override (I suspect in C# they are tied to their virtual/non-virtual function system). In C# I think an abstract class implementing an interface also needs to provide implementation for that interface, contrarily to Java or the present proposal IIRC. |
Added notes about abstract properties, |
Requiring Also it's not clear to me how this plays with visibility "inheritance". E.g. currently you don't have to specify That said, In general I'm in favor of proper abstract classes, good job! |
I see what you mean, but one also have to think about implemented methods in the abstract class, which can be overriden too: abstract class WhatAndWhere {
abstract public function where() : String;
public function what() return "it's what it is";
}
// style 1, no override for implementation
class SomeAnswers extends WhatAndWhere {
function where() return "In the universe";
override function what() return "42";
}
// style 2: with override
class TrueAnswers extends WhatAndWhere {
override function where() return "here";
override function what() return "what it is";
} All in all I prefer style 1. If it matters you can always specify visibility (and get an error if you attempt to e.g. change a public to private). But at least when you see override you know you trully did have a change of default behaviour, unlike style 2 where that information is lost. In my view that information is more important for a programmer (we spend a lot of time reading declarations) than knowing when a mandatory method was removed from an abstract class (it would just become a useless method, and it happens unfrequently). In fact --and this is a separate question-- Why do we need the Not that I don't like it, in fact with complex return types and optional |
I am in favour of requiring override - it reduces the chance of typos/misunderstandings from going unnoticed, which is really what I like about override in "normal" classes in the first place. |
You are right. I was thinking: "override function wot()" - "wot does not
override anything", but "function wot()" will generate "missing abstract
what", so no real problem there.
I still have a slight preference for 'override', mainly for consistency and
to allow a default implementation in the future without breaking anything.
…On Mon, Jan 13, 2020 at 10:13 AM Emugel ***@***.***> wrote:
@hughsando <https://github.com/hughsando>
If you make a typo in the case of abstract classes, it gets you an error
because you have not implemented something. Therefore what is the added
benefit, could you provide an example?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#69?email_source=notifications&email_token=AAMWTVXA6EIYY6XGA43JKO3Q5PE6DA5CNFSM4JWUHDG2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEIXLLAY#issuecomment-573486467>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAMWTVSTRJPBTGE35O6KTNLQ5PE6DANCNFSM4JWUHDGQ>
.
|
Requiring For
So extern abstract class AbstractClassFromJava {
function thisMethodHasImplementationInJava():String;
abstract function butThisMethodDoesNot():String;
}
class Implementation extends AbstractClassFromJava {
// override function thisMethodHasImplementationInJava():String {
// return "We are just overriding Java implementation";
// }
override function butThisMethodDoesNot():String {
return "Abstract method in Java is implemented with Haxe! Cool!";
}
} |
Ok, so I misunderstood the "abstract class" thing. As it stands, it is not the sort of thing I would have ever wanted to use. |
Maybe it's simply a bare-metal consequence of their vtable of functions (e.g. you set the pointer to 0 and it requires 'implementation' again) rather than a real feature? In fact it's been a long time since I don't do c++ so IDK, it might be a decision left to the implementer. |
Maybe what abstract class competes against is private constructor, which also disallows direct instantiation of the class but still allow from inside itself or subclasses. Yes we have the whole |
I think of the "=0" as a vtable thing conceptually, but it is actually a compile-time thing. I have only ever seen it used once in real life. The combination of private constructor and not creating classes with dangling abstract classes covers the cases I would use, but an alternative might be "abstract function new" which would require a derived class to have a "new" (and call super I guess) |
Missing |
As for |
I disagree that missing abstract on class is sufficiently confusing to warrant the extra busy-work or requiring making synchronized changes (eg, add abstract function to base class requires all intermediate classes to change). Especially since the keyword is "abstract" which is super-confusing on a class. This is like the case with a private "new" - if you are looking through source-code, you have to do some searching. But compiling, documentation or comment can tell you. |
What if there are no abstract methods, but I still want the class to be abstract? |
I can see why you would want to infer the abstractness of a class. However, I'm worried about the confusion potential when it's not clear that/why a class is abstract. On the other hand, we'll have the same problem for required |
I'm not sure why you would want an abstract class with no abstract methods - perhaps a use case would help me understand. But a private constructor would have a similar effect. |
To be clear, we should definitely allow |
One possible use case for an abstract class with no abstract methods would be the Active Record pattern, where the default implementation to resolve the table name in database may use reflection, and you definitely want to override the class name. |
Yes you mean some class fields But easy workaround: class ActiveRecord {
// many implemented methods and...
abstract public function tableName() : String;
}
class BestScore extends ActiveRecord {
function tableName() return "BestScore";
} My knowledge of Haxe maybe lacking, but I have to ask what follows regarding the presence of The possibility to have non-static methods in abstract types has been removed recently IIRC (Edit: this is just for abstract Foo (String) {
// ...
abstract function bar();
} That is abstract methods in abstract types? If so, should we not want to drop the |
We seem at a deadlock. I fear I contributed to it. I want to withdraw my idea of having abstractness depend merely only unto the presence of an unimplemented abstract function and support the original proposal, with mandatory declaration of |
Another thing that might be worth mentioning is that This might be implied by
But still, depending on the implementation we might miss that check, so better to mention it and add unit-test later. |
We have decided to There was consensus that this feature is useful. An open debate is whether or not the abstract-ness of a class should be inferred by the compiler. We decided to implement abstract classes first and then discuss the inference as a followup issue. |
Introduce classes that provide incomplete implementation and cannot be instantiated directly.
Rendered version