So right now I have two classes of the same class type, e.g.
class foo : foo_type = object ... end
class bar : foo_type = object ... end
I'd like to have a third class that inherits from either foo or bar at runtime. E.g. (pseudo-syntax)
class baz (some_parent_class : foo_type) = object
inherit some_parent_class
...
end
Is this possible in OCaml?
Use case: I'm using objects for constructing AST visitors, and I'd like to be able to combine these visitors based on a set of runtime criteria so that they only do one combined traversal over the AST.
Edit: I think I have found a way to create the desired class using first-class modules:
class type visitor_type = object end
module type VMod = sig
class visitor : visitor_type
end
let mk_visitor m =
let module M = (val m : VMod) in
(module struct
class visitor = object
inherit M.visitor
end
end : VMod)
However, it seems a little roundabout to have to wrap a class in a module in order to make it "first-class". If there's a more straightforward way please let me know.
This is just a cleaner implementation of what you already suggested, but I would do it like this:
module type Foo = sig
class c : object
method x : int
end
end
module A = struct
class c = object method x = 4 end
end
module B = struct
class c = object method x = 5 end
end
let condition = true
module M = (val if condition then (module A) else (module B) : Foo)
class d = object (self)
inherit M.c
method y = self#x + 2
end
Not contrary to what Jeffrey said, but you can achieve this using first-class modules. Also, I'm not sure that you really need to create classes on runtime, maybe creating object would be enough. If what you want to get is different behavior, then this will be enough.
OCaml has a static type system. You can't do anything at runtime that would affect the type of something. Inheritance affects the types of things, so it can't happen at runtime.
(Your code also confuses types with values, which is understandable.)
There is probably a way to get close to what you want while retaining the desirable properties of static typing. What you actually need may be more like function composition, perhaps.
Related
I'm trying to create an overloaded function that will be called with the dynamic type of an object. I try to do this without interfering with the actual class structure underneath, as I don't have direct access (i.e. I cannot add virtual methods, etc.)
As a concrete example, let's think of an AST class structure that looks somewhat like this:
class ASTNode {}; // this one is fully abstract; i.e. there's a virtual void method() = 0;
class Assignment : ASTNode {};
class Expression : ASTNode {};
class StringExpr : Expression {};
class MathExpr : Expression {};
I want to write a function act that will take an instance of ASTNode as parameter and, depending on its actual dynamic type do something different.
The call will be something like this
std::shared_ptr<ASTNode> parsedAST = get_a_parsed_ASTNode(); // ... received from some parser or library
act(parsedAST);
Then, I want to act, depending on the dynamic type of the ASTNode.
void act(std::shared_ptr<MathExpr> expr)
{
// Do something with Math expressions, e.g. evaluate their value
};
void act(std::shared_ptr<StringExpr> expr)
{
// Do something with String expressions, e.g. write their value to the log
};
void act(std::shared_ptr<Expression> expr)
{
// do something with other types of expressions (e.g. Boolean expressions)
};
Currently though, I cannot call since they dynamic type will be maybe not the ``most concrete type''. Instead, I have to manually create a dispatcher manually as follows, but the method is a bit silly in my opinion, since it does literally nothing else but dispatch.
void act(std::shared_ptr<ASTNode> node_ptr)
{
if(std::shared_ptr<MathExpr> derived_ptr = std::dynamic_pointer_cast<MathExpr>(node_ptr))
{
act(derived_ptr);
}
else if(std::shared_ptr<StringExpr> derived_ptr = std::dynamic_pointer_cast<StringExpr>(node_ptr))
{
act(derived_ptr);
}
else if(std::shared_ptr<Expression> derived_ptr = std::dynamic_pointer_cast<Expression>(node_ptr))
{
// do something with generic expressions. Make sure that this is AFTER the more concrete if casts
}
else if( ... ) // more of this
{
}
// more else if
else
{
// default action or raise invalid argument exception or so...
}
};
This is especially annoying & error-prone since my class hierarchy has many (> 20) different concrete classes that can be instantiated. Also, I have various act-functions, and when I refactor things (e.g. add an act for an additional type), I have to make sure to pay attention to the correct order of if(dynamic_pointer_cast) within the dispatcher.
Also it's not that stable, since a change in the underlying class hierarchy will require me to change every dispatcher directly, rather than just the specific act functions.
Is there a better / smarter solution? Evidently I'd appreciate "native" solutions, but I'm willing to consider libraries too.
Never encountered such problem myself, but can think of the following solution.
Create you hierarchy that mimics original hierarchy, has virtual act, the base has base pointer, and each cast it to the corresponding derived pointer.
Now, to create the needed wrapper, you don't need properly ordered dynamic_cast, dispach on typeid string. So your dispatch is a map from string to wrapper factory.
Sure you need RTTI for typeid string, but you would need it for dynamic_cast as well.
There are already several Q&As on this "X does not implement Y (... method has a pointer receiver)" thing, but to me, they seems to be talking about different things, and not applying to my specific case.
So, instead of making the question very specific, I'm making it broad and abstract -- Seems like there are several different cases that can make this error happen, can someone summary it up please?
I.e., how to avoid the problem, and if it occurs, what are the possibilities? Thx.
This compile-time error arises when you try to assign or pass (or convert) a concrete type to an interface type; and the type itself does not implement the interface, only a pointer to the type.
Short summary: An assignment to a variable of interface type is valid if the value being assigned implements the interface it is assigned to. It implements it if its method set is a superset of the interface. The method set of pointer types includes methods with both pointer and non-pointer receiver. The method set of non-pointer types only includes methods with non-pointer receiver.
Let's see an example:
type Stringer interface {
String() string
}
type MyType struct {
value string
}
func (m *MyType) String() string { return m.value }
The Stringer interface type has one method only: String(). Any value that is stored in an interface value Stringer must have this method. We also created a MyType, and we created a method MyType.String() with pointer receiver. This means the String() method is in the method set of the *MyType type, but not in that of MyType.
When we attempt to assign a value of MyType to a variable of type Stringer, we get the error in question:
m := MyType{value: "something"}
var s Stringer
s = m // cannot use m (type MyType) as type Stringer in assignment:
// MyType does not implement Stringer (String method has pointer receiver)
But everything is ok if we try to assign a value of type *MyType to Stringer:
s = &m
fmt.Println(s)
And we get the expected outcome (try it on the Go Playground):
something
So the requirements to get this compile-time error:
A value of non-pointer concrete type being assigned (or passed or converted)
An interface type being assigned to (or passed to, or converted to)
The concrete type has the required method of the interface, but with a pointer receiver
Possibilities to resolve the issue:
A pointer to the value must be used, whose method set will include the method with the pointer receiver
Or the receiver type must be changed to non-pointer, so the method set of the non-pointer concrete type will also contain the method (and thus satisfy the interface). This may or may not be viable, as if the method has to modify the value, a non-pointer receiver is not an option.
Structs and embedding
When using structs and embedding, often it's not "you" that implement an interface (provide a method implementation), but a type you embed in your struct. Like in this example:
type MyType2 struct {
MyType
}
m := MyType{value: "something"}
m2 := MyType2{MyType: m}
var s Stringer
s = m2 // Compile-time error again
Again, compile-time error, because the method set of MyType2 does not contain the String() method of the embedded MyType, only the method set of *MyType2, so the following works (try it on the Go Playground):
var s Stringer
s = &m2
We can also make it work, if we embed *MyType and using only a non-pointer MyType2 (try it on the Go Playground):
type MyType2 struct {
*MyType
}
m := MyType{value: "something"}
m2 := MyType2{MyType: &m}
var s Stringer
s = m2
Also, whatever we embed (either MyType or *MyType), if we use a pointer *MyType2, it will always work (try it on the Go Playground):
type MyType2 struct {
*MyType
}
m := MyType{value: "something"}
m2 := MyType2{MyType: &m}
var s Stringer
s = &m2
Relevant section from the spec (from section Struct types):
Given a struct type S and a type named T, promoted methods are included in the method set of the struct as follows:
If S contains an anonymous field T, the method sets of S and *S both include promoted methods with receiver T. The method set of *S also includes promoted methods with receiver *T.
If S contains an anonymous field *T, the method sets of S and *S both include promoted methods with receiver T or *T.
So in other words: if we embed a non-pointer type, the method set of the non-pointer embedder only gets the methods with non-pointer receivers (from the embedded type).
If we embed a pointer type, the method set of the non-pointer embedder gets methods with both pointer and non-pointer receivers (from the embedded type).
If we use a pointer value to the embedder, regardless of whether the embedded type is pointer or not, the method set of the pointer to the embedder always gets methods with both the pointer and non-pointer receivers (from the embedded type).
Note:
There is a very similar case, namely when you have an interface value which wraps a value of MyType, and you try to type assert another interface value from it, Stringer. In this case the assertion will not hold for the reasons described above, but we get a slightly different runtime-error:
m := MyType{value: "something"}
var i interface{} = m
fmt.Println(i.(Stringer))
Runtime panic (try it on the Go Playground):
panic: interface conversion: main.MyType is not main.Stringer:
missing method String
Attempting to convert instead of type assert, we get the compile-time error we're talking about:
m := MyType{value: "something"}
fmt.Println(Stringer(m))
To keep it short and simple, let say you have a Loader interface and a WebLoader that implements this interface.
package main
import "fmt"
// Loader defines a content loader
type Loader interface {
load(src string) string
}
// WebLoader is a web content loader
type WebLoader struct{}
// load loads the content of a page
func (w *WebLoader) load(src string) string {
return fmt.Sprintf("I loaded this page %s", src)
}
func main() {
webLoader := WebLoader{}
loadContent(webLoader)
}
func loadContent(loader Loader) {
loader.load("google.com")
}
The above code will give you this compile time error
./main.go:20:13: cannot use webLoader (type WebLoader) as type Loader
in argument to loadContent:
WebLoader does not implement Loader (Load method has pointer receiver)
To fix it you only need to change webLoader := WebLoader{} to following:
webLoader := &WebLoader{}
Why this will fix the issue? Because you defined this function func (w *WebLoader) Load to accept a pointer receiver. For more explanation please read #icza and #karora answers
Another case when I have seen this kind of thing happening is if I want to create an interface where some methods will modify an internal value and others will not.
type GetterSetter interface {
GetVal() int
SetVal(x int) int
}
Something that then implements this interface could be like:
type MyTypeA struct {
a int
}
func (m MyTypeA) GetVal() int {
return a
}
func (m *MyTypeA) SetVal(newVal int) int {
int oldVal = m.a
m.a = newVal
return oldVal
}
So the implementing type will likely have some methods which are pointer receivers and some which are not and since I have quite a variety of these various things that are GetterSetters I'd like to check in my tests that they are all doing the expected.
If I were to do something like this:
myTypeInstance := MyType{ 7 }
... maybe some code doing other stuff ...
var f interface{} = myTypeInstance
_, ok := f.(GetterSetter)
if !ok {
t.Fail()
}
Then I won't get the aforementioned "X does not implement Y (Z method has pointer receiver)" error (since it is a compile-time error) but I will have a bad day chasing down exactly why my test is failing...
Instead I have to make sure I do the type check using a pointer, such as:
var f interface{} = new(&MyTypeA)
...
Or:
myTypeInstance := MyType{ 7 }
var f interface{} = &myTypeInstance
...
Then all is happy with the tests!
But wait! In my code, perhaps I have methods which accept a GetterSetter somewhere:
func SomeStuff(g GetterSetter, x int) int {
if x > 10 {
return g.GetVal() + 1
}
return g.GetVal()
}
If I call these methods from inside another type method, this will generate the error:
func (m MyTypeA) OtherThing(x int) {
SomeStuff(m, x)
}
Either of the following calls will work:
func (m *MyTypeA) OtherThing(x int) {
SomeStuff(m, x)
}
func (m MyTypeA) OtherThing(x int) {
SomeStuff(&m, x)
}
Extend from above answers (Thanks for all of your answers)
I think it would be more instinctive to show all the methods of pointer / non pointer struct.
Here is the playground code.
https://play.golang.org/p/jkYrqF4KyIf
To summarize all the example.
Pointer struct type would include all non pointer / pointer receiver methods
Non pointer struct type would only include non pointer receiver methods.
For embedded struct
non pointer outer struct + non pointer embedded struct => only non pointer receiver methods.
non pointer outer struct + pointer embedded struct / pointer outer struct + non pointer embedded struct / pointer outer struct + pointer embedded struct => all embedded methods
If I have a function which accepts an argument of multiple types, how can I enforce that the return must match the value of the input?
This comes up particularly when I want a method to work with any children of a parent type. For demonstration, consider something that is "barlike":
abstract struct Barlike
property bar: Int32
def initialize(#bar); end
end
abstract def make_clang_sound
abstract def serve_drinks
end
Now any struct can implement those two methods, and store that value
struct Bar1 < Barlike
def make_clang_sound
puts "bing bang bong"
end
def serve_drinks
puts "your drink sir"
end
end
struct Bar2 < Barlike
def make_clang_sound
puts "kling klang"
end
def serve_drinks
puts "here are your drinks"
end
end
Now what if I have a method that wants to use the bar and return a new one with an updated value (these are structs afterall):
def foo(arg : Barlike)
new_bar = arg.bar + 2
arg.class.new(new_bar)
end
this will return a Bar1 if a Bar1 is passed in and a Bar2 if that is passed in but it's not guaranteed:
def foo(arg : Barlike)
"howdy"
end
I'm going to be putting my foo into an abstract structure as well, so I need to guarantee that implementers of foo return the same type of Barlike that was given.
I tried
def foo(arg : Barlike) : arg.class
end
But that's a compile time error (arg cannot be used there like that)
I also tried
def foo(arg : Barlike) : typeof(arg)
end
which passes, but typeof here is just Barlike whereas I really need it to be only the thing that was passed in, only Bar1 or Bar2 and so on.
Can macros help?
The tool for this are free variables. That's essentially generics scoped to a single method.
# This method returns the same type as its argument
def foo(arg : T) : T forall T
arg
end
This would already solve the main part of your question.
However, it is currently not possible to apply type restrictions to free variables, for example restricting T to Barlike.
There are workarounds, though:
Use a macro to validate the argument type:
def foo(arg : T) : T forall T
{% raise "arg must implement Barlike" unless T < Barlike %}
arg
end
Delegate to another method with a type restriction:
def foo(arg : T) : T forall T
foo_impl(arg)
end
private def foo_impl(arg : Barlike)
arg
end
Both workarounds affect the implementation of the method. There is no way to specify such a type restriction for a abstract def. Number 2 might be feasible, if you make foo_impl abstract and require inheriting classes to implement this one, instead of foo.
But it's probably also fine to just go with the initial example using free variables, without the Barlike restriction. In practice, you probably don't gain much.
Here is something that works:
{% for sub in Barlike.subclasses %}
struct {{sub}}
def foo() : {{sub}}
{{sub}}.new(#bar+1)
end
end
{% end %}
full example
But it feels like this is trying to solve the wrong problem. It uses the #subclasses macro to generate a foo for all of the child structs.
You could also declare these as self methods inside the abstract class: example.
I have a method in Java like so:
public <T extends A & B> methodName(T arg, ...)
where A is a class and B is an interface.
In my kotlin class, I have another variable of type C, and I wish to achieve the following:
if (variable is A && variable is B) {
methodName(variable, ...)
} else {
// do something else
}
Is it possible to properly cast variable so that it may be used as an argument without errors?
Currently, the variable has a setter method, so smart casting isn't
available. However, I have also tested it with a local val and the
value is inferred to have type Any which doesn't help.
Kotlin does not support intersection types. This causes variable to be smart cast to Any, because that is the common ancestor of A and B.
However, Kotlin does support generic type constraints. You can use this to constrain a type parameter to one or more types. This can be used on both methods and classes. This is the syntax for functions (the equivalent of your methodName in Kotlin):
fun <T> methodName(arg: T)
where T : A,
T : B {
....
}
You can use this to get around your problem by creating a class which extends both A and B, and then delegates the implementation of these types to your object. Like this:
class AandB<T>(val t: T) : A by t, B by t
where T : A,
T : B
You can now call methodName by changing your if-test to check if it is a AandB<*>:
if (variable is AandB<*>) {
methodName(variable, ...)
}
You do need to wrap variable in a AandB somewhere though. I don't think you can do it if you don't have the type information for variable available anywhere.
Note: The AandB class does not implement hashCode, equals or toString. You could implement them to delegate to t's implementation.
Note 2: This only works if A and B are interfaces. You can not delegate to a class.
As #marstran points out, the when clause is how you specify multiple bounds. Here's a link to the documentation about upper-bounds. It's worth mentioning that you cannot have multiple bounds if one of your bounds is a generic type parameter.
You mentioned that you tried testing with smart-casting:
However, I have also tested it with a local val and the value is inferred to have type Any which doesn't help.
This is not the case for the current version of Kotlin (v1.4). You do not need to create an AandB class as you can use a val or local (captured) var to smart-cast to an intersection.
Here's an example (and runnable version):
interface I1 { fun one() = println("one") }
interface I2 { fun two() = println("two") }
class Both: I1, I2
val variable: Any = Both() // Starting with type 'Any'
if (variable is I1 && variable is I2) {
// Type is now '(I1 & I2)' Smart-cast from Any
variable.one()
variable.two()
}
Here's a link to more discussion and runnable example of Kotlin intersection types as of v1.4
This is a follow-up to the question asked earlier.
LIB_A
I have this base class in an external library, say, LIB_A.
class Instrument
{
// ...
}
LIB_B
I have this derived class in another external library, say, LIB_B, which of course references LIB_A.
class Bond : public Instrument
{
// ...
};
In LIB_B, I also have a Trader class that owns a pointer to the bond it's working with.
class Trader
{
public:
// ...
Bond* _bond;
};
LIB_C
I cannot touch LIB_A or LIB_B.
In my own code, a third "library" (I'm using the term loosely here), say, LIB_C, I'm trying to create a class that points to a Trader's Bond pointer, i.e.
class TradeHelper
{
public:
TradeHelper(Bond** bondPtr): _bondPtr(bondPtr) {}
Bond** _bondPtr;
};
with it being constructed by
Trader* t; // assume this is given and not null
TradeHelper* th = new TradeHelper(&(t->_bond))
An Aside (no need to read)
Why such a convoluted scheme? Well, Trader::_bond can change, and TradeHelper needs to know what that Trader's _bond is, at all times. So essentially, TradeHelper gets linked to a Trader. Which is why, if I had the freedom to do things my way, I would have done exactly as described—linked the two like this:
class TradeHelper
{
public:
TradeHelper(Trader* t): _trader(t) {}
Trader* _trader;
};
with it being constructed by
Trader* t; // assume this is given and not null
TradeHelper* th = new TradeHelper(t);
and simply referred to the Bond via _trader->_bond.
Alas, for reasons of history and just-the-way-things-are, the only thing I have available to me for constructing TradeHelper is a pointer to Trader::_bond, not the Trader itself. Hence my use of the double-pointer.
The Problem
Well, everything, as described, would work fine. But the real problem is that LIB_C cannot reference LIB_B, only LIB_A. What that means is that TradeHelper cannot know about Bond, only Instrument. My example rewritten, now looks like this:
class TradeHelper
{
public:
TradeHelper(Instrument** instPtr): _instPtr(instPtr) {}
Instrument** _instPtr;
};
And therein lies the problem, when I construct it:
TradeHelper* th = new TradeHelper(&(t->_bond));
As I learned in this question, there is no implicit conversion from Bond** to Instrument**.
I guess the abstract question is very similar to the one I asked previously: How can I pass a pointer-to-a-derived-class-pointer as a pointer-to-a-base-class-pointer, given that I am allowed to assume that the pointers would be used safely? In the previous question I sought what I was doing wrong, and having learned, I felt I needed to describe my situation in more detail for anyone to be able to suggest a way forward.
Reworded, I want object X to always know "where" another object Y's member is, but that member is a derived class, and object X only knows about the base class.
I've tinkered with pointer references and casting but can't seem to figure a way out.
I've reconstructed your example using dynamic_cast and I had no problems constructing TradeHelper this way. Is there a reason you can't use dynamic_cast in your code?
Trader trader;
Bond b;
trader._bond = &b;
Trader* t = &trader;
Instrument* inst = dynamic_cast<Instrument*>(t->_bond);
if (inst == NULL) {
std::cout << "dynamic_cast failed!" << std::endl;
return 1;
}
TradeHelper* th = new TradeHelper(&inst);
delete th;