Well I'm quite sure this is easy :)
I have an abstract tagged type NamedStructure having three fields in the private part of the spec:
name (a string)
structure (roughly an array)
number (an positive)
I then created a subclass Chord which is basically:
type Chord is new NamedStructure with null record;
Playing around with Spark, I need to initialize my chord objects but I face a problem.
Chord_Object : Chord := (NamedStructure'(Name => "",
Structure => (Others => False),
Number_Of_Notes => 0) with null record);
doesn't compile and the error message is
scalada-chords.adb:44:53: expected private type "NamedStructure" defined at scalada-namedstructures.ads:52
scalada-chords.adb:44:53: found a composite type
I don't find the correct construction using the extension aggregate and I don't see why. Any idea ?
The error suggests that NamedStructure is a private type and therefore cannot be initialized using an aggregate. You might try
type Chord is new NamedStructure with null record;
Chord_Object : Chord := (NamedStructure with null record);
although the instance fields of NamedStructure will now remain uninitialized.
Related
Let's take the following code as an example:
val immutableList: List<Any> = listOf<String>()
val mutableList: MutableList<Any> = mutableListOf<String>()
interface SuperList : List<Any>
interface SubList : SuperList, List<String>
As expected, assigning immutableList is allowed, which from my understanding of the docs is because it's marked to say it will only ever return values of T and never take them, so it doesn't matter if it's Any or a subclass.
Also as expected, assigning mutableList gives an error because it cannot offer that guarantee, as casting to MutableList<Any> would let you add an Any to a list of Strings and that would be bad.
I would expect the interface SubList to be fine for the same reason that immutableList is: List's generic functions will only give T, never take it, so returning a String would make both happy. However, its declaration throws the same error as mutableList:
Type parameter E of 'List' has inconsistent values: String, Any
Type parameter E of 'Collection' has inconsistent values: String, Any
Type parameter T of 'Iterable' has inconsistent values: String, Any
Why is this?
Things I've attempted, when trying to understand the cause:
Having SubList inherit from List<Any> directly rather than SuperList: Gives the same error, so this isn't due to something funky with the layers in the inheritance.
Having SuperList inherit from List<out Any> rather than List<Any>: Gives the error Projections are not allowed for immediate arguments of a supertype.
Having SuperList take a type parameter. This works but like... at that point why does SuperList even exist, lol. Much better for my use case to just take an entirely different approach to the goal than to do that.
Context:
My goal was a pair of Table and MutableTable types, and my initial idea was implementing this via extending List<List> and List<MutableList>, respectively. But I wanted to boil the question down to its simplest form, and so chose non-generic classes to use for the sample code.
I have other ideas on how to implement the types, so I'm not looking for an answer to that. I'd just like to understand the root issue that stops this particular approach from working, so that in the future I don't run into other pitfalls with it in ways that might be harder to dodge.
I stuck with some simple thing) Let's say I have following:
interface IMessagePayload // marker interface
data class IdPayload(
val id: Long
) : IMessagePayload
data class StringPayload(
val id: String,
) : IMessagePayload
Then I have a class:
data class Message<T : IMessagePayload>(
val id: String,
val payload: T,
)
Also I have some interface describing processor of this message:
interface IMessageProcessor<T : IMessagePayload> {
fun process(message: Message<T>)
}
And some implementation:
class ProcessorImpl : IMessageProcessor<IdPayload> {
override fun process(message: Message<IdPayload>) {
}
}
Now I wanna have a map of such processors. Lets use some enum type as a keys of this map:
enum class ActionType {
UPDATE,
DELETE,
ADD
}
private var map = mutableMapOf<ActionType, IMessageProcessor<IMessagePayload>>()
map[ActionType.ADD] = ProcessorImpl() // <-- error here
And that's where the problem occurs. I cannot put my ProcessorImpl into this map. The compiler says that there is an error: Type mismatch. Required: IMessageProcessor. Found: ProcessorImpl().
I could declare the map in the following way (using star projection):
private var map = mutableMapOf<ActionType, IMessageProcessor<*>>()
But in this case I cannot call processors's process method fetching it from the map by key first:
map[ActionType.ADD]?.process(Message("message-id", IdPayload(1))) // <-- error here
Compiler complains: Type mismatch. Required nothing. Found Message<IdPayload>
What am I doing wrong? Any help is appreciated.
This is about variance.
IMessageProcessor is defined as interface IMessageProcessor<T : IMessagePayload>; it has one type parameter, which must be IMessagePayload or a subtype.
But it is invariant in that type parameter; an IMessageProcessor< IdPayload> is not related to an IMessageProcessor<IMessagePayload>. In particular, it's not a subtype.
And your map is defined with a value type IMessageProcessor<IMessagePayload>. So its value cannot be an IMessageProcessor< IdPayload>, because that's neither the value type, nor a subtype. Hence the compile error.
In this case, the simplest way to get it to compile is to change your map:
private var map = mutableMapOf<ActionType, IMessageProcessor<out IMessagePayload>>()
The only difference there is the out; that tells the compiler that the value IMessageProcessor is covariant in its type parameter. (It may help to think of out as meaning ‘…or any subtype’. Similarly, you could make it contravariant by using in, which you might think of as ‘…or any supertype’.)
This lets you store in the map an IMessageProcessor for any subtype of IMessagePayload.
However, if you do that, you'll find that you can't use any value you pull out of your map — because it can't tell which messages the processor can handle, i.e. which subtype of IMessagePayload it works for! (The compiler expresses this as expecting a type parameter of Nothing.)
In general, it's often better to specify variance on the interface or superclass itself (declaration-site variance) rather than the use-site variance shown above. But I can't see a good way to do that here, because you have multiple generic classes, and they interact in a complicated way…)
Think for a moment what IMessageProcessor's type parameter means: it's the type of message that the processor can consume. So an IMessageProcessor<A> can handle messages of type Message<A>.
Now, a subtype must be able to do everything its supertype can do (and usually more) — otherwise you can't drop that subtype anywhere that's expecting to use the supertype. (That has the grand name of the Liskov substitution principle — but it's really just common sense.)
So an IMessageProcessor<B> is a subtype of IMessageProcessor<A> only if it can handle at least all the messages that an IMessageProcessor<A> can. This means it must accept all messages of type Message<A>.
But Message is invariant in its type parameter: a Message<B> is not directly related to a Message<A>. So you can't write a processor that handles them both.
The most natural solution I can find is to specify variance on both Message and IMessageProcessor:
data class Message<out T : IMessagePayload>( /*…*/ )
interface IMessageProcessor<in T : IMessagePayload> { /*…*/ }
And then use a wildcard in your map to make it explicit that you don't know anything about the type parameters of its values:
private var map = mutableMapOf<ActionType, IMessageProcessor<*>>()
That lets you safely store a ProcessorImpl() in the map.
But you still have to use an (unchecked) cast on the values you pull out of the map before you can use them:
(map[ActionType.ADD] as IMessageProcessor<IdPayload>)
.process(Message("4", IdPayload(4L)))
I don't think there's any easy way around that, because the problem is inherent in having values which are processors that can handle only some (unknown) types of message.
I'm afraid the best thing would be to have a rethink about what these classes mean and how they should interact, and redesign accordingly.
An API I consume returns (among other fields) a mandatory telephone1 and an optional telephone2. However, the JSON I fetch always contains both fields and a missing entry is displayed as an empty string.
{
"telephone1": "+1 555 1234",
"telephone2": ""
}
When the response is mapped to a pojo, is it preferable to translate the empty string to null? Such that:
data class(
val telephone1: String,
val telephone2: String?
}
To me, this better communicates the possible states. Should I, though? Are there drawbacks?
At the first sight, problem boils down to different checks before further data processing: x == null or x.isEmpty(). But while nullability check is generally enforced by kotlin compiler (unlike unemptiness), it seems to be a better option.
But there are still some situations when usage of null (without any compiler errors) may lead to problems in runtime (mainly related to interop with languages without enforced nullability): like implicit convertion of null to literal string "null" (when concatenating with another string), or even NPE when passed to method accepting String! (platform type) and not annotated properly.
Sticking to DDD principles, the better option would be declaration of separate datatypes:
sealed class OptionalPhoneNumber
data class PhoneNumber(val value: String) : OptionalPhoneNumber() //You may also add some checks in init block that `value` is really a phone number, not just a set of random chars
object EmptyPhoneNumber : OptionalPhoneNumber()
and defining your data class as:
data class Data (
val telephone1: PhoneNumber,
val telephone2: OptionalPhoneNumber
)
Type system will enforce you to do x is PhoneNumber checks, and thanks to smart casts it's further usage will be type-safe:
if (telephone2 is PhoneNumber) {
println(telephone2.value)
}
Hey I just found out about typecasts, but I dont understand the concept behind it? Why would you use something like that. I tried to make an example to understand it better:
interface Fuel {
//Fuel.kt
var usingFuel : Boolean
var typeFuel : String
fun printInfo(){
println("Using this Fuel type: $typeFuel")
}
}
class Airplane(name : String, age : Int, amountFuel: Double) : Vehicle(name, age, amountFuel), Fuel {
//Airplane.kt
override var usingFuel: Boolean = true
override var typeFuel: String = "Kerosin"
override fun printInfo() { //Prints name, age etc of object
super<Vehicle>.printInfo()
super<Fuel>.printInfo()
}
}
//Main.kt
var airplane : Airplane = Airplane(args)
var otherKerosin : Fuel = airplane
otherKerosin.fuelType = "Other Kerosin"
otherKerosin.printInfo()
airplane.printInfo()
And the output of otherKerosin.printInfo() is like the output of airplane.printInfo(), only that the fuel type is different. Now why should I do this, instead of creating a new airplane and changing the fuelType variable?
This line
var otherKerosin : Fuel = airplane
does not create a new instance of something. It's just getting a new reference to the same instance, but narrows its type to just the Fuel interface. Any change you make using otherKerosin also changes the original Airplane assigned to airplane (and vice versa) because both of these variables are pointing at the same instance.
In your given example, there would be no reason to do this. otherKerosin is needlessly restricting its type to Fuel, which hides the extra functions Airplane may have that aren't part of the Fuel interface. It provides you nothing that you can't do with the original airplane reference. But if you were returning your airplane from a function and the classes that call that function only need to work with a Fuel, you might want to simply return a Fuel so you aren't exposing more than you have to to the outside world. For example:
interface FuelProvider {
fun provideFuel(): Fuel
}
class AirplaneProvider: FuelProvider {
override fun provideFuel(): Fuel = Airplane() // Airplane is cast to Fuel
}
There's almost never a need to cast to a more narrow typed local variable. But sometimes you have a member property with a narrower type than the object you have at hand and you'll still want to assign it to that property. For example:
class FuelStorage(var fuel: Fuel? = null)
val storage = FuelStorage()
val airplane = Airplane()
storage.fuel = airplane // the Airplane is cast to Fuel to put it in the `fuel` property.
The FuelStorage class here doesn't care if its Fuel is an Airplane or some other type of Fuel.
I can think of maybe one example where you might want to do this, and that's if you have a long function you're writing and you want to limit your abilities with a variable to keep the available actions simpler. In a very long function, this could help you keep track of what you're doing. But, if a function is getting long enough for this to actually be helpful, it's probably a code smell.
Note, the type of casting you asked about and I discussed above is implicit casting, which is done automatically by assigning something to a property or variable for which the instance is a match, or by returning something from a function where the return type is a match.
You can also explicitly cast with as or as? which is done when the type you're casting to is not a known match for the type you're casting from. For example, if you have a Fuel and you want to cast it to an Airplane. A Fuel is not always an Airplane so you must explicitly cast to change the reference type. This will fail with an exception if the underlying instance is not in fact an Airplane, unless you use the safe cast as?.
And you can also smart cast by checking if a local variable is of a certain type or not null with an if check. After the check, the compiler can assume that the variable is referring to the checked type.
I want to prove some facts about imperative object-oriented program. How can I represent a heterogeneous object graph in Coq? My main problem is that edges are implicit - each node consists of an integer label modelling object address and a data structure that models object state. So implicit edges are formed by fields inside data structure that model object pointers and contain address label of another node in a graph. To ensure that my graph is valid, adding new node to the graph must require a proof that all fields in a data structure that is being added refer to nodes that already exist in the graph. But how can I express 'all pointer fields in a data structure' in Coq?
It depends on how you represent a data structure, and what kinds of features the language you want to model has. Here's one possibility. Let's say that your language has two kinds of values: numbers and object references. We can write this type in Coq as:
Inductive value : Type :=
| VNum (n : nat)
| VRef (ref : nat).
A reference (or pointer) is just a natural number that can be used to uniquely identify objects on the heap. We can use functions to represent both objects and the heap as follows:
Definition object : Type := string -> option value.
Definition heap : Type := nat -> option object.
Paraphrasing in English, an object is a partial function from strings (which we use to model fields in the object) to values, and a heap is a partial function from nats (that is, object references) to objects. We can then express your property as:
Definition object_ok (o : object) (h : heap) : Prop :=
forall (s : string) (ref : nat),
o s = Some (VRef ref) ->
exists obj, h ref = Some obj.
Again, in English: if the field s of the object o is defined, and equal to a reference ref, then there exists some object obj stored at that address on the heap h.
The one problem with that representation is that Coq functions make it possible for heaps to have infinitely many objects, and objects to have infinitely many fields. You can circumvent this problem with an alternative representation that only allows for functions defined on finitely many inputs, such as lists of pairs, or (even better) a type of finite maps, such as this one.