DXE7: "type A = type B" and var x (of type A):= A.create leads to E2010 incompatible type compile error. Why? - class

A. Short summary of the problem:
type
A = class(TObject)
end;
B = type A;
The compiler error E2010 incompatible types: 'B' and 'A' is shown, when you instantiate a variable of class B in the following style:
var
TheB: B;
begin
TheB:= B.Create;
..
I can avoid that problem by removing the second "type", so the declaration is the standard one:
type
A = class(TObject)
end;
B = A;
But in my opinion, the error should not come, even WITH the second "type", because A is not directly used (The second "type" tells the compiler to see both classes as individuals, see http://docwiki.embarcadero.com/RADStudio/Seattle/en/Declaring_Types for details). Can someone explain, because of what reason the error ignores my opinion? (o;
B. Complete history and more complex details:
First of all: The error:
[dcc32 Fehler] gboDHL.pas(165): E2010 Inkompatible Typen: 'Origin' und 'CountryType'
(which means "incompatible types" in english),
occurs in the following line of code:
AShipmentOrder.Shipment.Shipper.Address.Origin:= DHL_geschaeftskundenversand_api_2.Origin.Create;
Now here is the background:
I try to communicate with the "new" DHL Geschäftskundenversand API v2.2 which still uses SOAP to create a shipment order. DHL_geschaeftskundenversand_api_2 is the completely generated unit from the integrated delphi xe7 WSDL generator for that service.
AShipmentOrder is the instance which represents the top level xml node of the request.
The class "Origin" is implemented/generated this way:
type
CountryType = class(TRemotable)
private
Fcountry: country2;
Fcountry_Specified: boolean;
FcountryISOCode: countryISOType;
Fstate: state;
Fstate_Specified: boolean;
Fcountry_: country;
Fcountry__Specified: boolean;
FcountryISOCode_: countryISOType;
Fstate_: state2;
Fstate__Specified: boolean;
procedure Setcountry(Index: Integer; const Acountry2: country2);
function country_Specified(Index: Integer): boolean;
procedure Setstate(Index: Integer; const Astate: state);
function state_Specified(Index: Integer): boolean;
procedure Setcountry_(Index: Integer; const Acountry: country);
function country__Specified(Index: Integer): boolean;
procedure Setstate_(Index: Integer; const Astate2: state2);
function state__Specified(Index: Integer): boolean;
published
property country: country2 Index (IS_OPTN) read Fcountry write Setcountry stored country_Specified;
property countryISOCode: countryISOType read FcountryISOCode write FcountryISOCode;
property state: state Index (IS_OPTN) read Fstate write Setstate stored state_Specified;
property country_: country Index (IS_OPTN) read Fcountry_ write Setcountry_ stored country__Specified;
property countryISOCode_: countryISOType read FcountryISOCode_ write FcountryISOCode_;
property state_: state2 Index (IS_OPTN) read Fstate_ write Setstate_ stored state__Specified;
end;
Origin = type CountryType; { "http://dhl.de/webservice/cisbase"[GblElm] }
The "property" Origin of AShipmentOrder.Shipment.Shipper.Address is implemented/generated this way:
type
NativeAddressType = class(TRemotable)
...
published
...
property Origin: Origin Index (IS_OPTN or IS_REF) read FOrigin write SetOrigin stored Origin_Specified;
...
end;
If it is unclear, let me say, that ´AShipmentOrder.Shipment.Shipper.Address´ is of class NativeAddressType
I'm using Delphi XE7 on Windows 10, 64bit, compiling to 32bit.
The delphi WSDL generator has different problems, which I had to manage before, and it is really not "nice" that in the output the property names are identical to the class names, but that is not changeable, it seems.
The class "Origin" is not the only class in that generated unit which is named as the property it belongs to, but the error only occurs, when such a class is implemented as
type
A = type B
I tried to find a description of that special declaration variant, but that is quite hard, because the keywords are too often used.
On http://www.delphibasics.co.uk/RTL.asp?Name=Type I found the following explanation:
1.type Name = Existing type  
Refers to an existing type, such as string by a new Name.
 
2.type Name = type Existing type  
This has the same effect as above, but ensures that at run time, variables of this type are identified by their new type name, rather than the existing type name.
If I understand that correctly, that means that in my example the class Origin is not identified anymore as CountryType, but as Origin. That should be fine, because the property Origin is declared as to be of class Origin.
While going on to try to understand that problem, I manually renamed The class "Origin" in the generated unit to OriginType (delphi used that postfix "Type" with several other classes in that unit, not clear, why it has not used it with the Origin-Type). After that, I can exclude a name-conflict, because now the error is
[dcc32 Fehler] gboDHL.pas(165): E2010 Inkompatible Typen: 'OriginType' und 'CountryType'
There seems to be no reason because of what that error occurs.
After some hours without some ideas I found this Embarcadero WIKI entry: http://docwiki.embarcadero.com/RADStudio/Seattle/en/Declaring_Types
After reading and thinking about that, I understood, that the "type" in A = type B is not necessary in that case, because there is no need to handle class A in another way than class B, so I removed that manually in the generated unit and now, it works fine.
I also understand, that a special option in the generator was checked to prevent "name conflicts". If this option is not checked, this problem also should be solved (but maybe some others come around (o; ).
Maybe this helps someone to spent more time outside than with a problem like that (o;
But in the end, I do not understand what was the problem here, because all properties were of type "Origin" and later of "OriginType", also this type was created with Origin.Create and later with OriginType.Create. So the "CountryType" was never used, except for the class declaration of "Origin" / "OriginType". In my opinion this should not lead to that problem, but it does.
Can somebody explain that?
Thank you in advance
Kai

You are getting: E2010 Incompatible types: 'Tb' and 'Ta', which might seems odd:
type
Ta = class
end;
Tb = type Ta;
var
b: Tb;
begin
b := Tb.Create; // E2010 Incompatible types: 'Tb' and 'Ta'
end.
Ta and Tb are two distinct types.
From Type Compatibility you can see that none of the conditions listed indicates that the two distinct types are compatible.
Type Compatibility
Every type is compatible with itself. Two distinct types are compatible if they satisfy at least one of the following conditions.
They are both real types.
They are both integer types.
One type is a subrange of the other.
Both types are subranges of the same type.
Both are set types with compatible base types.
Both are packed-string types with the same number of characters.
One is a string type and the other is a string, packed-string, or Char type.
One type is Variant and the other is an integer, real, string, character, or Boolean type.
Both are class, class-reference, or interface types, and one type is derived from the other.
One type is PAnsiChar or PWideChar and the other is a zero-based character array of the form array[0..n] of PAnsiChar or PWideChar.
One type is Pointer (an untyped pointer) and the other is any pointer type.
Both types are (typed) pointers to the same type and the {$T+} compiler directive is in effect.
Both are procedural types with the same result type, the same number of parameters, and type-identity between parameters in corresponding positions.
The reason for the compiler error is thus: When you call Tb.Create, the compiler identifies that with Ta.Create and since b is of a distinct non-compatible type, it is not accepted.
You can call that a flaw, but it follows strict type rules and can easily be corrected like shown below.
Declaring Tb = class(Ta) would resolve the compiler error since Tb is derived from Ta.
Also declaring Tb = Ta would resolve the compiler error, since they would denote the same type (not two distinct types) and thus assignment compatible.

Related

Dart/Flutter : The meaning of "whether some code is annotated or inferred is orthogonal to whether it is dynamic or some other type"

https://dart.dev/guides/language/effective-dart/design#types
If the code is type annotated, the type was explicitly written in the
code.
If the code is inferred, no type annotation was written, and Dart
successfully figured out the type on its own. Inference can fail, in
which case the guidelines don’t consider that inferred.
If the code is dynamic, then its static type is the special dynamic
type. Code can be explicitly annotated dynamic or it can be inferred.
In other words, whether some code is annotated or inferred is
orthogonal to whether it is dynamic or some other type.
The above explanation is extremely abstract and I'm not sure exactly what this means.
Especially the last sentence, does it mean that "it may be inferred as another type even though it is type-annotated as'dyanmic'"?
But maybe I feel it's not right.
Because I remember being told by the IDE during development that something like "because it's a dynamic type, you can't access that member."
If not, I would like a more specific explanation of what it means after all.
It would be helpful if you could get some clues.
Basically, a variable can be type annotated:
int x = 1;
also, it can be inferred:
var x = 1; // dart knows x is an integer because you assigned 1 to it.
A variable can be dynamic, meaning it's type can change.
That's what the three first sentences mean, the last sentence is saying that a dynamic variable can be either inferred or annotated:
dynamic someFunction() {
return 1;
}
dynamic x = 'aaa'; // annotated
var y = someFunction(); // inferred
So weather a variable is annotated or inferred has nothing to do with weather it is dynamic or not.

Is int type in Dart a value type or reference type?

The int type in Dart has default value of null. null is an object of type Null class. (as per Dart documentation). Also, in Dart, int derives from class Object.
Hence,
int i = 10;
print(i.runtimeType is Object); // returns true
This makes me believe that int is not a value type like in other languages (such as C#) but a reference type.
If I am correct, then-
int i = 10;
means i is a reference variable holding the reference to an int object 10.
Is this correct? If not, I would appreciate if a link to the description in the documentation is shared.
Till now, I've been unable to find any proper explanation and hence have come to this conclusion myself.
Thanks.
Yes, Dart's int type is a "reference type".
Dart does not have value types at all, all values are instances of a class, including integers. (At least technically, function values makes their classes very hard to see.)
Integers are immutable and pretends to be canonicalized.
If a and b are int values and a == b, then identical(a, b) is guaranteed to be true, so a and b looks like they are the same object, but it's unspecified whether that's because they really are the same object, or because identical just cheats and does == for integers.
That means that you can largely treat int as a "value type". Whether it is copied on assignment or parameter passing, or you are passing a reference to the same object, is impossible to tell apart. The language ensures that, because it allows the implementations to do whatever is more efficient.
In practice, some integers are unboxed inside functions, some integers are stored as a value in the reference itself, and some are real objects.
(That's also one of the reasons you can't use an Expando with an int).
(In the current Dart language, all types annotations are nullable, meaning that you can assign null to int x;. With the upcoming Null Safety feature, that changes. Types will only be nullable if you write them as such, so int x = 1; would not accept a null value, but int? x; would. And null is an object too, the only instance of the class Null.)
int is a value type in the sense that if you pass int value into a function and change the value of a parameter inside function, it won't affect outer scope.
void add(int inner) {
inner += 1;
}
int outer = 0;
add(outer);
print(outer); // 0, unchanged
But int is still a class even though its name starts from lowercase letter. There was a huge discussion about its naming and lots of people consider it an inconsistency.
Yes int is a class (it even extends num) and therefor has common methods to use on. But one the other side it is different than "normal" classes since you don't have to use a constructor like
int i = int(3);
See int's class documenation https://api.dart.dev/stable/2.8.4/dart-core/int-class.html
Everything in Dart is an object, int, double or num may look like keywords but they are built-in abstract classes. Since they are abstract classes which means they can not be instantiated, they do not start with an uppercase letter.
try this line,
print('2 is instance of "int" class :\t${ 2 is int}');
this will result in true.
And regarding your concern about 'null' :
In Dart, like JavaScript and Python, everything that a variable can hold is an object including null. Every object including null is an instance of some class and all these classes inherit from Object class.
your can refer this link for more info.
Hope this helps.

Understanding OO class definition

This is an extract from IB Computer Science Higher Level Paper 2 November 2010, Q1b
I am trying to understand what are the “roles” of: “Node” and “item” in the following class definition
<< from question >>
class Node (1)
{
public int item; (2)
public Node next: (3)
public Node(int d) (4)
{
item = d; (5)
next = null; (5)
}
public void displaynode()
{
output(Item + “ “);
}
<< end of question extract >>
The numbers in parentheses after certain lines in the class definition are my references used in the questions below.
Is the following correct?
(1) Node is the name of the class which is used when I want to create a new, single Node by issuing
Node x = new Node(5)
which results in a new Node containing the value 5, stored in (4,5).
(2,3) These are data items with the labels item and next, of type integer (2) and Node (3) respectively (I don’t understand what it means to have type Node) ????
Being public can I access and alter the contents by using following references x.item, x.Node ???
(4) This is the method Node which accepts a single, integer parameter named d.
(5) The input parameter “d “ gets put in the object variable “item”, and “next” is set to the value Null when a new Node is created.
(1) Node is the name of the class which is used when I want to create a new, single Node by issuing Node x = new Node(5) which results in a new Node containing the value 5, stored in (4,5).
This is a reasonable explanation.
(2,3) These are data items with the labels item and next, of type integer (2) and Node (3) respectively (I don’t understand what it means to have type Node) ???? Being public can I access and alter the contents by using following references x.item, x.Node ???
Please call them variables rather than "data items". item and next are instance variables, and since next is of type Node, we can say that class Node is recursively defined. This an implementation of a linked list in which each element contains an integer value and a reference to the next element.
You're correct about the meaning of public.
(4) This is the method Node which accepts a single, integer parameter named d.
It's important that you recognize that this is a constructor method which is automatically called to initialize the state of a Node when it's instantiated.
(5) The input parameter “d “ gets put in the object variable “item”, and “next” is set to the value Null when a new Node is created.
I'd rather say the value of input parameter d gets assigned to the variable item. I wouldn't call it an object variable - in some languages, ints are considered objects, in others not. In some perspectives, variables themselves are seen as primitive objects, distinct from their values. Regardless, I think it detracts from the clarity to say "object variable".
For further study, look into the following distinctions:
Variable vs value: A variable is an element that holds a value. Variables allow us to write code that operate over different values. Values can be anything - numbers, text, arrays, records, objects, functions, and more, depending on the language.
Class vs object: A class is a blueprint for a state machine, while an object is a specific instance of one. Objects have state and methods which operate on that state.
Class vs type: A class declares what goes on inside a state machine. A type declares (what is known for) a set of values. Value types are associated with the operators that can be called on those types of values. Object types declare the methods that can be called on those types of objects (but not what those methods do).
In many OOP languages and discussions, class and type are conflated. Even variable and value are commonly conflated. As a computer scientist, you should know and understand the differences.

Scala - How is a variable of type Any stored in memory?

How is it possible to create variable of type Any?
And why does isInstanceOf[Int] print true?
I declared x to be Any, not Int.
How does it work? What is happening behind the scenes?
val x = 4: Any // OK
x.isInstanceOf[Int] // true
x.isInstanceOf[String] // false
[EDIT] Maybe to rephrase my question:
How does val x = 4: Any look like in memory?
And once it is stored in memory as Any type, how can I later say that this particular blob of bytes is Int, but not say String?
Does it come along with some kind of information what was the "original" type? Here for example if I typed 4 AND LATER said this is Any type, would it store this original type of 4 as an Int?
Scala language is defined to support the notion of inheritance polymorphism. In other words, if there is some type T which inherits from type U, then any value of type T can be assigned to a variable of type U:
class T extends U
val x: U = new T // compiles
Same thing with Any and Int: in Scala, Int inherits from Any, therefore it is possible to store an integer in an Any variable:
val x: Any = 4 // essentially the same as your example
Also, all of the runtimes Scala runs on know what type of value is actually stored in a variable, regardless of the static type of this variable. This is important for many features of the language, in particular, virtual method overrides, but it also allows you to do manual checks and downcasts, which is what your code does (the checks). In other words, the isInstanceOf method checks the runtime type of a value stored in a variable, not the static type known at the compile time (which would be quite pointless).

Delphi Classes: Property vs Get/Set methods

So I'm kinda new to OO programming. Delphi has properties which are intended to be a "more elegant" way to acess class data than getters/setters (read it here usage of property vs getters/setters in business classes).
When should I use the fields directly and when should I use getters/setters inside the property? I'm gessing only when the data needs to be manipulated, but I'm not sure.
Edit:
Is it wrong to omit a setter that does nothing but return the value of the field itself?
property Field :integer read FField write FField;
Why properties?
For starters, a quick summary from the documentation on properties:
A property, like a field, defines an attribute of an object. But while a field is merely a storage location whose contents can be examined and changed, a property associates specific actions with reading or modifying its data. Properties provide control over access to an object's attributes, and they allow attributes to be computed.
Why not only setter and getter?
Separation of storage and access can indeed be achieved by the use of just getters and setters, and leave the property be. That is true, but the question you link to originates from a language difference: Delphi does have properties, and the answers there already explain why to use them. The two most obvious reasons are (1) cleaner code and (2) assignment capability. I think this answer deals with it quite extensive already.
Furthermore, without the use of properties, getters and setters are always needed, where with properties they are not. Assume a setter implementation, but no getter: a property can directly read the field.
Class completion
When you just declare a property's name and its type, Delphi's class completion defaults to reading a private field and a private setter which sets the private field. Mind that this is just the default configuration, which you again can modify to your needs. When you fully specify the property declaration, class completion will comply and add a private field, a getter and/or setter as required for your declaration.
Properties without getter and setter
Is it wrong to omit a setter that does nothing but return the value of the field itself?
When a property has no getter nor setter and it just reads and writes the field, then you could conclude that there is no difference beside being consistent. But that is not the case. The field and the property have distinct names, and therefore possibly distinct meaning. Meaning that you can give. See Using properties instead of fields in class methods of the same unit is a bad practice?.
When to use a getter or setter?
... I'm gessing only when the data needs to be manipulated ...
Well, that is partly true. Manipulation is one of the many reasons. Consider a Price property of type String, and its private field FPrice:
Limitation: When the price needs to be equal or higher than zero,
Delegation: When FPrice is part of another field, or when it otherwise is beyond the responsibility of this class,
Verification: When the price may only have two decimals behind the comma,
Interpretation: When the price is entered in thousands, but should be stored in cents,
Effect: When the price has consequences for another field, for example rate or margin,
Activation: When an edit to the price requires immediate action, for example updating the GUI,
Conversion: When the price is entered in dollars but should be stored in yen,
Cancelation: When the price does not make sense, for example when it is entered in scientific notation.
Note that a Price property is quite rudimentary. Leaving its setter or getter for future implementation is very well possible. But imagine more advanced properties which cannot do without setter or getter:
A field that needs to be created before consulting:
function TMyObject.GetBarelyUsed: TRare;
begin
if FBarelyUsed = nil then
FBarelyUsed := TRare.Create(Self);
Result := FBarelyUsed;
end;
An item can be selected, but the item itself does not know what to do. Instead the owner does. Notice the complete absence of the private field in this case:
procedure TItem.SetSelected(Value: Boolean);
begin
if Value <> Selected then
begin
if Value then
Owner.Selection.Add(Self)
else
Owner.Selection.Remove(Self);
end;
end;
An image control, specialized in viewing your own image format. Assignment of the FileName property involves: checking the correct file extension, checking file existance, storing the file name in the private field, loading the file, adjusting the pictures' dimensions, or else undoing the previous assignment:
procedure TAwDxfImage.SetFileName(const Value: TFileName);
begin
if FFileName <> Value then
if SameText(ExtractFileExt(Value), '.' + SDxf) and
FileExists(Value) then
begin
FFileName := Value;
FGraphic.LoadFromFile(FFileName);
FGraphic.SetBounds(Width, Height);
end
else
begin
FFileName := '';
FGraphic.Clear;
end;
end;
Source: NLDelphi
In addition to #NGLN answer there is another use case for property getter/setter.
Accessing class instances through interface is only possible via instance methods. If you have to access property in such case you have to implement getter/setter methods.
type
IField = interface
function GetField: integer;
procedure SetField(value: integer);
property Field: integer read GetField write SetField;
end;
TField = class(TInterfacedObject, IField)
protected
FField: integer;
function GetField: integer;
procedure SetField(value: integer);
public
property Field: integer read GetField write SetField;
end;
var
f: IField;
x, n: integer;
...
f := TField.Create;
f.Field := 5;
f.SetField(6);
n := f.Field;
x := f.GetField;
Of course, depending whether you need only read or write access to that property you can omit setter or getter in your interface declaration.
Keep in mind that accessing instance through interface gives all interface implemented methods public visibility. That is why in above example you can call f.GetField despite it being declared protected (or even private).
What is unacceptable is to do this
TMyClass = class
private
public
Fubar :integer;
end;
the remainder of your examples are fine. I would be happy to receive code from you that reads like this
TMyClass = class
private
FFu : integer;
public
property Fu :integer read FFu write FFu;
end;
because I can confidently change it to
TMyClass = class
private
FFu : integer;
procedure SetFu(Value : Integer);
function GetBar() : string;
public
property Fu :integer read FFu write SetFu;
property Bar : String read GetBar;
end;
without breaking existing code.
I have a personal dislike of setters that do nothing
procedure TMyClass.SetFu(Value : Integer);
begin
FFu := Value;
end;
But in truth it is harmless.
Does that help?
This would be a valid reason or incentive for using a setter
procedure TMyClass.SetFu(Value : Integer);
begin
if FFu <> Value then begin
FFu := Value;
if Assigned(FAfterFooChanged) then
FAfterFooChanged(FFu);
end;
end;
not 'manipulation' as such ...