If Object Pascal forced you to add a visibility specifier to all record declarations, all Pascal code from the 1980s and 1990s would become invalid at a stroke.
Personally I think too detailed information hiding is counterproductive.
The benefits are in the first order aspects, the rest is micromanaging.
If you go that way, maybe identifiers should have ACLs ? >:D
Personally I think too detailed information hiding is counterproductive.
The benefits are in the first order aspects, the rest is micromanaging.
If you go that way, maybe identifiers should have ACLs ? >:D
Personally I think too detailed information hiding is counterproductive.
The benefits are in the first order aspects, the rest is micromanaging.
Informating hiding is hiding identifiers from others scopes (classes/units/whatever). I firmly believe in keeping that simple. (IMHO the whole "strict*" was already worse than the actual problem). private/protected/public is good enough.
QuoteIf you go that way, maybe identifiers should have ACLs ? >:DACL are access control lists, lists like file permissions on windows that list who (and or which group) can access what.
Personally I think too detailed information hiding is counterproductive.
The benefits are in the first order aspects, the rest is micromanaging.
Informating hiding is hiding identifiers from others scopes (classes/units/whatever). I firmly believe in keeping that simple. (IMHO the whole "strict*" was already worse than the actual problem). private/protected/public is good enough.
I basically agree. The problem is that the object pascal language has a peculiar notion of private (and protected), since a private member of a class is visible not only within the class to which it belongs, but also outside, within the unit where the class itself is defined. This does not happen for example in C++ and Java. Hence the need for the 'strict' keyword to restrict visibility.
Is anyone of you attracted to the record/class idea I mentioed above?I think In Delphi mode you don't need an advancedrecords modeswitch to give you advanced records.
Like making records implicitly advanced and object-wise, like supporting everything that a class can but is still allocated on the stack.
I feel this bringing a modeswitch into fpc feels very deprecated to me atleast.
Of course they lack proper inheritance.Since when? KOL or FV are counter-examples. That's a load of Boris. Look how fp is build.
In my head, there shouldnt even be a need for a modeswitch to advanced records, it should be implicitly possiblyWe are reluctant to enable new features by default in mode ObjFPC, cause we're trying to be as backwards compatible as possible. That would also answer the following question:
Is anyone of you attracted to the record/class idea I mentioed above?No, we're not. There are more important things to work on, namely features like dynamic packages, anonymous functions, extended RTTI, improving optimizations than inventing yet another dialect (because that is all that it would be).
Like making records implicitly advanced and object-wise, like supporting everything that a class can but is still allocated on the stack.Use the object type for that.
I feel this bringing a modeswitch into fpc feels very deprecated to me atleast.The mode and modeswitch concept is a very strong point of FPC and easily allows it to incorporate multiple language dialects and to easily add new features without breaking existing code.
Sorry, confused message.That's the idea. If you need inheritance then use the appropriate type.
I meant advanced records currently lack inheritance. Perhaps they always will?
I meant advanced records currently lack inheritance. Perhaps they always will?Probably, because adding inheritance to advanced records would result in something that already exists: the old "object" (or very close to it.)
Interesting.That's what I meant with worse than the problem. The addition (and having six levels) is worse than the original problem (three levels with some shortcuts for use within the same unit).I basically agree. The problem is that the object pascal language has a peculiar notion of private (and protected), since a private member of a class is visible not only within the class to which it belongs, but also outside, within the unit where the class itself is defined. This does not happen for example in C++ and Java. Hence the need for the 'strict' keyword to restrict visibility.Personally I think too detailed information hiding is counterproductive.Informating hiding is hiding identifiers from others scopes (classes/units/whatever). I firmly believe in keeping that simple. (IMHO the whole "strict*" was already worse than the actual problem). private/protected/public is good enough.
The benefits are in the first order aspects, the rest is micromanaging.
Note that the exceptions are partially rooted in the unit system, a concept that e.g. Java doesn't have, and C++ is only discussing about in committees. C++ is 30 years back on that front, so it is logical that they don't support it.
From my Pascal experience and understanding I expect Records to be plain data structures and Objects like the Classes to be the real OOP features. So for simplicity I'd rather hope that the advanced records are dropped.No.
Actually I quite liked using the Object type, especially as singleton. But I'm more and more reluctant because it is not fully compatible with the Class type. Override of methods e.g. is not possible and I stumbled into strange errors time by time. The problem for the missing features is, that in the beginning the object type seems to be enough and later I reach a point where incompatibilities occur, requiring to change to the class type. It's a rare case, but still I always have it in mind when I consider using the Object type. So it would be nice if the Object type would be further developed to be fully orthogonal to the Class type. E.g. a class could be derived from an object (and vice versa?).The object type is the old object system from Turbo Pascal times. As it was quite a bit different from the Delphi class types they do have their different behaviours. Thus it's also not possible to have one inherit from the other, because they present completely different concepts.
The object type is the old object system from Turbo Pascal times.
What was that- Turbo pascal 5.5? I no longer have access to my manual collection, but I think it was in an addendum accompanying the TP5 manuals.
From my Pascal experience and understanding I expect Records to be plain data structures and Objects like the Classes to be the real OOP features. So for simplicity I'd rather hope that the advanced records are dropped.I would agree. I doubt that adding new and new syntactic features make a language really better.
Override of methods e.g. is not possible...Why?? There is no key word "override" for old style objects, but you can have a virtual method and, in a heir type, define another method with the same arguments and virtual modifier - and it overrides the old one:
Thus it's also not possible to have one inherit from the other, because they present completely different concepts.
I know obviously, that a class is stored as a pointer to the date which itself is on the heap, and object is pure date itself at the stack, but ignoring this for a second, they should be behave the same ,right?
Thus it's also not possible to have one inherit from the other, because they present completely different concepts.Do you mean on implementation/memory side or on syntax side?
Also while we don't consider the object type to be deprecated (like Delphi does) we don't really have an intention to develop it further.Yes, I realized that. Except for embedded targets there also seems no need for the object type. But perhaps its also a henn/egg-problem. If there were full compatibility than maybe it would be used more, which could result in a higher motivation for improvements :)
Thanks! I wasn't aware of that.Override of methods e.g. is not possible...Why?? There is no key word "override" for old style objects, but you can have a virtual method and, in a heir type, define another method with the same arguments and virtual modifier - and it overrides the old one:
Code: [Select]tempFoo:= Foo[1];
tempFoo.DoSomething;
//or even..
for tempFoo in Foo
do tempFoo.DoSomething
end;
This would allow the use of static memory and still avoid explicit pointer handling, when dealt with references.
The former. For starters an object might be located on the stack or the heap, calling constructors can be considered optional and they or may not have a pointer to a VMT depending on the inheritance and the presence of virtual methods. In contrast a class instance is always located on the heap, one must call a constructor to instantiate it and they always have a pointer to a VMT. Not to mention that the VMT of the later (https://svn.freepascal.org/cgi-bin/viewvc.cgi/trunk/rtl/inc/objpash.inc?revision=43418&view=markup#l101) is much more vast than that of objects (https://svn.freepascal.org/cgi-bin/viewvc.cgi/trunk/packages/rtl-extra/src/inc/objects.pp?revision=40598&view=markup#l1127).Thus it's also not possible to have one inherit from the other, because they present completely different concepts.Do you mean on implementation/memory side or on syntax side?
For starters an object might be located on the stack or the heap, [...]Thats clear, but both variables, of type Object and Class carry the memory address of the data block. So regarding the memory access there should be no difference whether its allocated on the stack or heap or whereever else in the RAM.
In contrast a class instance is always located on the heap
[Object...] calling constructors can be considered optional [...]Even with Class/Object compatibility this still could stay that way. If the constructor were called from an object type, then the Constructor would be called as plain procedure without reserving memory, as the static memory of an object is reserved already. I think that would be straight forward to use.
[Class...] one must call a constructor to instantiate it [...]
[Object...] and they or may not have a pointer to a VMT depending on the inheritance and the presence of virtual methods. [...]Ok, thats a real incompatibility now. There arises the question if backward compatibility on binary side is always given, or if internal structures could be changed time by time.
[Class...] and they always have a pointer to a VMT. Not to mention that the VMT of the later is much more vast than that of objects. [...]
Yes, there is a difference. A class can be allocated using a class type and the class that is really instantiated could have a larger size. Let's assume that allocating a class on the stack would work. Then the following code would fail:For starters an object might be located on the stack or the heap, [...]Thats clear, but both variables, of type Object and Class carry the memory address of the data block. So regarding the memory access there should be no difference whether its allocated on the stack or heap or whereever else in the RAM.
In contrast a class instance is always located on the heap
That's the same reason why you need to allocate object instances on the heap if you want to work with virtual inheritance and such.Can you give an example for that?
For class types this is an integral part of the concept and thus combining them essentially reduces classes to objects.The class reference feature "class of T..." wouldn't be applicable to objects (that means no "object of T.."), but classes still can have it. I still think objects and classes could behave quite orthogonal without the reduce of any features.
Firstly let me rewrite your code to my syntax in mind and comment inside. The interface part stays the same.First you declare it as "an object", thus it's on the stack and then suddenly there's a heap allocation thanks to the constructor. How is a user to know what is going on now, especially when they're somewhere down in the code? No, that's not a good design.As you can see, the object/class mixture in that special case wouldn't result in useful code, but it would still be legit code. In the example the limitations of the object type are already on syntax level as it's a result of the memory allocation (time and place) and of the behaviour of the constructor-call. Thus the compiler wouldn't have to do special checks for which features are allowed or not for object or class type.
type TMyClass = class fMyField: LongInt; end; TMyClasses = class of TMyClass; TMySubClass = class(TMyClass) fMySubField: LongInt; end; procedure Whatever; var o: object(TMyClass); //An instance of TMyClass is allocated on the stack. // Short form for: // Type TMyObject = object(TMyClass); // o: TMyObject; c: TMyClasses; begin c := TMySubClass; o := c.Create; // This is an unfortunate line of code, as 'o' is already // allocated on the stack and Create results into a second memory // allocation, because it's called by the class type 'c' and not by an // object type, which would just call the procedure Create without // memory allocation. The address of the class type is written // into 'o' which leads into a memory leak (until the procedure is left). Writeln(TMySubClass(o).fMySubField); // That would still work, as 'o' references the // instantiated class and not the original object. end;
But perhaps I'm missing something...
I'm not talking about hypothetical code, I'm talking about existing code:That's the same reason why you need to allocate object instances on the heap if you want to work with virtual inheritance and such.Can you give an example for that?
The following (hypothetical) code should work with fully static memory:
PS E:\fpc\git> fpc -FEtestoutput .\fpctests\tobjtest.pp
Free Pascal Compiler version 3.0.4 [2019/10/27] for i386
Copyright (c) 1993-2017 by Florian Klaempfl and others
Target OS: Win32 for i386
Compiling .\fpctests\tobjtest.pp
tobjtest.pp(10,4) Warning: Virtual methods are used without a constructor in "TMyObj"
tobjtest.pp(18,4) Warning: Virtual methods are used without a constructor in "TMySubObj"
tobjtest.pp(39,3) Warning: Variable "obj" does not seem to be initialized
tobjtest.pp(40,9) Warning: Variable "subObj" does not seem to be initialized
Linking testoutput\tobjtest.exe
42 lines compiled, 0.2 sec, 64192 bytes code, 4100 bytes data
4 warning(s) issued
PS E:\fpc\git> .\testoutput\tobjtest.exe
An unhandled exception occurred at $00401544:
EAccessViolation: Access violation
$00401544
First you declare it as "an object", thus it's on the stack and then suddenly there's a heap allocation thanks to the constructor. How is a user to know what is going on now, especially when they're somewhere down in the code? No, that's not a good design.It just makes no sense to mix the object and class type within the one line of calling the constructor. The compiler could even cover that by prompting an error, but that are details.
I'm not talking about hypothetical code, I'm talking about existing code:I see. But there's an issue:
[...]
And here's the BOOM:
The whole discussion is moot anyway however as we are not going to change that objects and classes are different.I know. Still I hope that I can give you inspirations when you think about that topics and also this helps me to further understand the language and the internals of the compiler. And finally its just interesting to think about it.