I have started learning Ada a few weeks ago. I understand that limited in some contexts declares a limited type, for whom copying of objects is not allowed
From Ada Reference Manual 2012 7.5 1/2
A limited type is (a view of) a type for which copying (such as for an assignment_statement) is not allowed. A nonlimited type is a (view of a) type for which copying is allowed.
However, since an interface type is inherently abstract, an 'interface object' cannot be created, and thus cannot be copied. Is keyword limited redundant here? What's the difference between limited interface and interface?
type Abstract_Fruit_Type is interface;
type Abstract_Fruit_Type is limited interface;
The key distinction is in ARM 3.9.4 12/2
A type derived from a nonlimited interface shall be nonlimited.
So if you want to implement the interface with a limited type then you must mark the interface with limited keyword. Then you will be able to implement this interface with limited or non-limited types.
If you omit limited keyword in interface description then all its implementations will be non-limited types only.
I think I figured it out:
A limited interface can be used to extend a synchronized interface and its subcategories task interface and protected interface, while a (non-limited) interface cannot.
-- This is allowed
type Abstract_Type is limited interface;
type Task_Type is task interface and Abstract_Type;
-- This is not allowed
type Abstract_Type is interface;
type Task_Type is task interface and Abstract_Type;
-- error: (Ada 2005) task interface cannot inherit from non-limited interface
Both task interface and protected interface, and thus their parent -- all synchronized interface are inherently limited. Ada Reference Manual 2012 3.9.4 12/2 specifies the following
A type derived from a nonlimited interface shall be nonlimited.
Which means
A type that is limited cannot be derived from a nonlimited interface.
Event though interface types themselves are abstract, they are used to create concrete types, whose objects can be defined. Due to the above restriction, the limited keyword in limited interface is necessary.
Limited in Ada type declarations means "this thing does not have assignment."
In Ada's generic or in interface the keywords like limited or private are inverted: you are saying "the thing being represented here cannot be assumed to have property X". So you can instantiate a private-typed generic-parameter with an Integer, but inside the generic itself you can only count on the properties from the generic formal specification.
Related
I'm trying to learn F# by converting an existing .NET Core solution in C# over, one project at a time. I currently have an interface in C# with nullable reference types:
public interface IVehicle {
public int GetWheels();
public string? GetLicensePlate();
}
And this interface is implemented in a number of other projects which depend on this one. I'm trying to convert one of these over, but if I try
type Car(serialNumber: string) =
interface MyProjectInterfaces.IVehicle with
member this.GetWheels() = 4
member this.GetLicensePlate() =
match LicensePlateService.GetLicencePlate(serialNumber) with
| Some(x) -> System.Nullable(x)
| None -> System.Nullable()
I get the error:
This expression was expected to have type 'string' but here has type 'Nullable<string>'
This doesn't seem to affect value types, so I'm assuming it's something to do with string being a reference type.
What do I do to solve this? Presumably I could rewrite the underlying interface to use F# and thus options, but there are other C# projects that implement the interface and I don't want to have to rewrite the whole solution in one go. Or am I doing F# completely wrong?
This is a confusion between C# 8's nullable references and nullable value types, aka Nullable<T>. If you look at the definition of Nullable<T>, you'll find:
public struct Nullable<T> where T : struct
which means it's only for value types. int? is short for Nullable<int>.
That's different from nullable references.
The nullability modifier for reference types doesn’t introduce a new type. Reference types are still nullable and compiling string? results in IL that’s still just System.String.
The difference at the IL level is the decoration of nullable modified types with a NullableAttribute.
In other words, it's just a compiler construct - one which isn't visible to F#.
match LicensePlateService.GetLicencePlate(serialNumber) with
| Some(x) -> x
| None -> null
will be the correct, albeit non-idiomatic replacement.
Using reflection, we can get the type name, storage size and the function of the given type(such as uint64, user-defined struct and so on). Even, we can modify some fields of the given type.
How does golang implement reflections? I guess the following ways:
Every type in golang, including user-defined type, itself has the information about type name, fields name and the function name. Golang reflection just reads these information or call the function.
Through some mechanism, Golang can get the type name, storage size and so on. And the type itself doesn’t have these information.
I have read the golang reflection code roughly. I guessed that golang used the second way.
Who can describe the concrete implement of reflection? Or recommend me some documents? Reading all code is difficult for me.
This is just an overview and it might be not 100% accurate but hopefully you will find it helpful.
At build time Go linker will embed information about all types used by the application into the executable (https://github.com/golang/go/blob/master/src/runtime/symtab.go#L39)
Each interface value contains a pointer to the data type descriptor (https://github.com/golang/go/blob/master/src/runtime/type.go#L14)
During conversion from a type that is known at compile time to an interface value Go compiler will point type descriptor of this interface value to the concrete type descriptor (it is known at compile time!).
E.g. when you call reflect.TypeOf(uint(87)):
an interface value is created by the compiler that references uint type descriptor
this interface value is passed to reflect.TypeOf function as argument
reflect.TypeOf function uses type descriptor that has been stored by the linker in the executable to get the align (and other) information about uint type.
The description of interfaces is well described here: The Laws of Reflection.
A variable of interface type stores a pair: the concrete value
assigned to the variable, and that value's type descriptor.
Basically, type are known statically from your code. More flexible interface types keep the original underlying type for getting back to the original data type.
I'm trying to define a Fortran derived type that has a private allocatable array. However, I would like to be able to access the array via a public pointer for use in other modules. E.g.
type,public :: test
private
real,allocatable :: a(:,:,:)
contains
real,pointer,dimension(:,:,:),public :: point => a
end type test
I just get a compiler error when attempting it like the above.
Is this possible without writing a subroutine that does the pointing for me?
No.
The syntax error is perhaps because you have the pointer component in the type bound procedure part of the type definition (after the contains), not in the component part (before the contains).
Beyond syntax, there are some problems with what you want to do:
You cannot associate a pointer with a component of a type definition. Pointers can be associated with components of objects (a subobject). Similarly, you cannot associate a pointer with something that doesn't have the target attribute. Types and components of types can't have the target attribute. Variables of that type, or objects pointed at by pointer components of an object may have the target attribute.
You cannot associate a pointer with something that isn't allocated. If something isn't allocated then there isn't anything to point at.
An initializer for a pointer component cannot refer to something that is allocatable. In addition to the target attribute the thing that it refers to must have the SAVE attribute. As the case with the TARGET attribute, variables have the save attribute, not type or component definitions.
Associating a pointer with a component of an object may defeat the point of making the component private in the first place. This leads to the question - what are you trying to do?
I'm having some difficulties getting my head around inheritance in Ada, and with some syntax.
My goal is to derive from an abstract type with a record, and use a different data type in the record field. Here's what I've been able to compile:
type Base is abstract new Parent.ParentType with record
X:Access_Type;
end record
type Child is new Base with record
n:Integer;
end record;
But I don't want to have this additional n field, I'd like to have X be an integer in the child type. I can't get the compiler to be happy with it. Something like the following is what I want:
type Base is abstract new Parent.ParentType with tagged record
X:Access_Type;
end record;
type Child is new Base with record
X:Integer;
end record;
Unfortunately, I can't figure out how to tag the base type which I think would allow me to reassign the X field. (Without tagging, the compiler complains of conflicting declarations.)
Can someone shed some light on this? I'm quite new to OO programming in general and I'm finding Ada's type approach more confusing than the usual class approach.
Are you sure you are not just wanting to nest some records ?
type Base is abstract new Parent.Parent_Type with record
X : Float;
end record;
...
type child_rec is
X : integer;
end record;
...
type Child is new Bases.Base with record
C : Child_Rec;
end record;
Which will allow you to refer to
My_Base.X;
and
My_Base.C.X;
Of course this can be done without any of the OO features too....
I'm not sure what problem you are trying to solve by changing the type of X in a derived type. As suggested in Ada 95 Rationale: II.1 Programming by Extension, extension of a tagged type adds components to those inherited from the base type. You may be looking for a way to specify parameters for a derived type using discriminants.
Addendum: It may help to understand that Ada's support for common object-oriented programming principles is not limited to tagged types.
The Ada Programming Language: Object-Oriented Programming (OOP) outlines the historical perspective. Prior to the advent of tagged types, Ada was considered object-based, with strong support for data abstraction, encapsulation, messaging, modularity, and inheritance; tagged types expanded the support for polymorphism, and later additions refined the feature.
A Comparison of the Object-Oriented Features of Ada 95 and Java offers a detailed comparison with a (possibly) more familiar language.
Base has to be tagged, because you can't say is abstract new Parent.Parent_Type unless Parent.Parent_Type is tagged, and that means that any derived type such as Base must be too.
The problem is that, as you have it, any code that can see Child could see two Xs; the one in Base and the one in Child. The compiler won't let you be ambiguous; when others read your code and see My_Child.X, how will they know which X you meant?
One way round this would be to make the full declaration of Base private, so that there's only one visible possibility for My_Child.X:
package Bases is
type Base is abstract new Parent.Parent_Type with private;
private
type Base is abstract new Parent.Parent_Type with record
X : Float;
end record;
end Bases;
with Bases;
package Children is
type Child is new Bases.Base with record
X : Integer;
end record;
end Children;
Are there any languages that allow changing the access modifier of a given member at runtime?
For example for hiding/showing information depending on the context where an object is being used.
Most languages can do this, but it often comes with a performance penalty. For example, you could change the accessibility of a private constructor in Java with the following.
Constructor constructor = MyClass.class.getDeclaredConstructor(paramTypes);
constructor.setAccessible(true);
MyClass instance = (MyClass)constructor.newInstance(params);
Look at the methods available on the class object in your favorite language and you'll see a number of ways to get at methods or fields, and once you have a handle on those, you can abuse them to your heart's content.