I want to implement a collision library using the interface Collidable
type Collidable interface{
BoundingBox() (float64,float64,float64,float64)
FastCollisionCheck(c2 Collidable) bool
DoesCollide(c2 Collidable) bool
Collide(c2 Collidable)
}
It has predefined shapes like.
type Circle struct{
X,Y,Radius float64
}
The idea is that I can do
type Rock struct{
collision.Circle
....
}
which then implements the interface Collidable, so I can pass it to a Spatial Hash Map (that expects a collidable). Only thing needed to do would be to override the Collide() function to my needs.
However the functions in type circle can not handle the type rock, even tough it has a circle embedded.
func (c1 *Circle) DoesCollide(i Collidable) bool{
switch c2 := value.(type) {
case Circle:
//doesn't fire, as it is of type Rock (unknown in this package)
//Needed is something like
//if i_embeds_Circle then c2 := i_to_Circle
}
}
Is this possible?
Is there a better way?
You are trying to use an object oriented design pattern with inheritance. This is not how to do this in Go. Beside, interface names end in 'able' in Java or equivalent object oriented languages. In Go the convention is to end interface names with 'er'.
To answer your question about the Rock, I would suggest that all thing that can collide into another thing implements the method CollisonShape() returning a collison.Shaper (e.g. Circle) that you will use to test collison. Here collison is the name of your package.
// This interface is defined in the collison package.
// Any object that may collide must implement that method.
type Collider interface {
CollisonShape() Shaper
}
// This function defined in the collison package
// test if two Collider collide into each other.
func Collide(c1, c2 Collider) bool {
shape1, shape2 := c1.CollisonShape(), c2.CollisonShape()
...
}
// This is how you would define an object that can collide.
type Rock struct {
shape *collison.Circle
...
}
// Implements the Collider interface.
// The return type must be the same as in the interface.
func (r *Rock) CollisonShape() collison.Shaper {
return r.shape
}
As you see, we use a method to access the collison shape of the rock. This allow us to write
if collison.Collide(rock, spaceCraft) {...}
This answer your question on how to do get the collison Shape of Rock.
If you want to avoid the call to the CollisonShape() method in the Collide() function, you will have to pass directly the collison.Shaper.
The method Collide would be defined in the collison package as
func Collide(shape1, shape2 Shaper) bool {...}
You then would have to write
if collison.Collide(rock.shape, spacecraft.shape) {...}
This design would be slightly more efficient, but the price to pay is less readable code which is frown upon by experienced Go programmers.
If you want Circle to be an embedded struct in rock you would then have to define it the following way. Embedding the shape saves allocation time for the Circle and some work for the GC.
type Rock struct {
shape collison.Circle
....
}
if collison.Collide(&rock.shape, &spacecraft.shape) {...}
If you want to use an anonymous embedded struct, you then would have to write
type Rock struct {
Circle
....
}
if collison.Collide(&rock.Circle, &spacecraft.Rectangle) {...}
As you see, the code gets less and less readable, and less convenient to use. The shape is not abstracted anymore. Using anonymous embedded struct should be limited to the very few cases where it really make sense.
By using the initially suggested CollisonShape() method, you could easily change your Rock structure into this one without breaking any code.
type Rock struct {
shape collison.Circle
...
}
func (r *Rock) CollisonShape() collison.Shaper {
return &r.shape
}
This now make the shape and embedded struct. The use of a method to get the shape decouples the internal implementation of Rock from the access to the shape. You can change the internal implementation of Rock without needing to change code in other places.
This is one of the reason why Go doesn't support inheritence. It creates a very strong dependency and coupling between the base class and derived classes. Experience has shown that people often regret such coupling as the code evolves. Object composition is preferred and recommended and well supported by Go.
If efficiency is your goal, every Collider should have one position which changes and a bounding box with a width and height that doesn't change. You can save a few operations using these values for the bounding box overlap test. But this is another story.
Not sure how off the mark this is, but posting it in case it helps you in any way.
http://play.golang.org/p/JYuIRqwHCm
If you are calling a legacy library which is not extensible (and cannot detect Rock, only Circle), there seems to be only one solution, pass a Circle.
See this example, where I use a non-anonymous field 'c' for Rock
(That means Rock has to implement the interface, which is a simple delegation to Circle.Shape())
type Shaper interface {
Shape()
}
type Circle struct{}
func (c *Circle) Shape() {}
type Rock struct{ c *Circle }
func (r *Rock) Shape() { r.Shape() }
func DoesShape(s Shaper) {
fmt.Println("type:", reflect.TypeOf(s))
switch st := s.(type) {
case *Circle:
fmt.Println("Shaper Circle %+v", st)
default:
fmt.Println("Shaper unknown")
}
}
func main() {
c := &Circle{}
DoesShape(c)
r := &Rock{c}
DoesShape(r.c)
}
Then the output is:
type: *main.Circle
Shaper Circle %+v &{}
type: *main.Circle
Shaper Circle %+v &{}
I have solved a similar problem by slightly modifying the base class. Not sure whether this is the solution you were looking for.
import "fmt"
type IShaper interface {
Shape()
}
type Rect struct{}
func (r *Rect) Shape() {}
type Circle struct{}
func (c *Circle) GetCircle() *Circle { return c }
func (c *Circle) Shape() {}
type Rock struct{ *Circle }
type ShapeWithCircle interface {
GetCircle() *Circle
}
func DoesShape(s IShaper) {
if sc, ok := s.(ShapeWithCircle); ok {
fmt.Printf("Shaper Circle %+v\n", sc.GetCircle())
} else {
fmt.Println("Shaper unknown")
}
}
func main() {
DoesShape(&Circle{})
DoesShape(&Rock{&Circle{}})
DoesShape(&Rect{})
}
That is, add a trivial function GetCircle() so that anything embedding a Circle has a function to get the (possibly embedded) circle. Then anybody needing a circle can trivially write an interface (ShapeWithCircle here) allowing one to test whether GetCircle() is defined and, if so, call it to get the embedded circle.
Play with it at https://play.golang.org/p/IDkjTPrG3Z5 .
Related
I used to do C++ development several years ago and back then I found it difficult to combine template programming with OOP. Currently I program in Swift and I tried doing some of the things I struggled with then.
This Swift code will illustrate the problem:
// protocol is like Java interface or C++ pure virtual base class
protocol Log {
// want to able to add elements from a collection of Ints, but
// it should be any sort of collection that
// can be treated as a sequence
func add<T: SequenceType where T.Generator.Element == Int>(values: T)
}
class DiscreteLog: Log {
var vals: [Int] = []
func add<T: SequenceType where T.Generator.Element == Int>(values: T) {
for v in values {
vals.append(v)
}
}
}
class ContinousLog: Log {
var vals: [Double] = []
func add<T: SequenceType where T.Generator.Element == Int>(values: T) {
for v in values {
vals.append(Double(v))
}
}
}
// I don't have to know whether the log is Continuous or Discrete
// I can still add elements to it
var log: Log = ContinousLog()
log.add([1, 2, 3])
// and elements can come from any kind of sequence, it does not need
// to be an array
log.add(["four": 4, "five: 5].values)
So the problem is that if the C++ code defined as as:
virtual void add(vector<Int> elements>)
Then sure I could have multiple subclasses implement this method, but I could never provide anything but vectors as arguments.
I could try changing it to something more generic using iterator:
virtual void add(vector<Int>::iterator elements>)
But I am still limited to using vector iterators. So I guess I would have to write something like:
template<typename Iterator>
virtual void add(Iterator elements>)
But that will give compile errors as template based arguments are not allowed for virtual methods.
Anyway I wondered if this sort of thing is possible in modern C++.
C++ templates and C#/Swift/Java generics are different things.
They are both "pattern code" in a sense (they are patterns that generate code), but C#/Swift/Java generics use type erasure and "forget" almost everything about the types they work with, while C++ templates are elephants. And elephants never forget.
It turns out that can make an elephant forget, but you have to tell it to. The technique of "forgetting" about details of a type is known as "type erasure" or "run time concepts".
So you want to type erase down to the concept of "a sequence of integers". You want to take any type, so long as it is a sequence of integers, and be able to iterate over it. Seems fair.
boost has such type erasures. But who wants to always rely on boost?
First, type erase an input iterator:
template<class T>
struct input_iterator:
std::iterator<
std::input_iterator_tag, // category
T, // value
std::ptrdiff_t, // distance
T*, // pointer
T // reference
>
{
struct erase {
virtual void advance() = 0;
virtual erase* clone() const = 0;
virtual T get() const = 0;
virtual bool equal(erase const& o) = 0;
virtual ~erase() {}
};
std::unique_ptr<erase> pimpl;
input_iterator(input_iterator&&)=default;
input_iterator& operator=(input_iterator&&)=default;
input_iterator()=default;
input_iterator& operator++() {
pimpl->advance();
return *this;
}
input_iterator operator++(int) {
auto copy = *this;
++*this;
return copy;
}
input_iterator(input_iterator const& o):
pimpl(o.pimpl?o.pimpl->clone():nullptr)
{}
input_iterator& operator=(input_iterator const&o) {
if (!o.pimpl) {
if (pimpl) pimpl->reset();
return *this;
}
pimpl = std::unique_ptr<erase>(o.pimpl->clone());
return *this;
}
T operator*() const {
return pimpl->get();
}
friend bool operator==( input_iterator const& lhs, input_iterator const& rhs ) {
return lhs.pimpl->equal(*rhs.pimpl);
}
friend bool operator!=( input_iterator const& lhs, input_iterator const& rhs ) {
return !(lhs==rhs);
}
template<class It>
struct impl:erase{
It it;
impl(impl const&)=default;
impl(It in):it(std::move(in)){}
virtual void advance() override { ++it; }
virtual erase* clone() const override { return new impl(*this); }
virtual T get() const override { return *it; }
virtual bool equal(erase const& o) override {
return static_cast<impl const&>(o).it == it;
}
};
template<
class It,
class=std::enable_if<
std::is_convertible<
typename std::iterator_traits<It>::reference,
T
>{}
>
>
input_iterator(It it):pimpl( new impl<It>{it} ) {}
}; // input_iterator
Next, have a range template. This is a container that stores non-type erased iterators, and exposes enough to iterate over those iterators.
template<class It>
struct range {
It b; It e;
It begin() const { return b; }
It end() const { return e; }
range() = default;
range(It start, It finish):b(std::move(start)),e(std::move(finish)) {};
range(range&&)=default;
range(range const&)=default;
range& operator=(range&&)=default;
range& operator=(range const&)=default;
template<class R,
class R_It=std::decay_t<decltype(std::begin(std::declval<R>()))>,
class=std::enable_if< std::is_convertible<R_It, It>{} >
>
range( R&& r ):
range(std::begin(r), std::end(r))
{} // TODO: enable ADL begin lookup
};
The above type is really basic: C++1z has better ones, as does boost, as do I have in my own code base. But it is enough to handle for(:) loops, and implicit conversion from containers with compatible iterators.
Finally our sequence type:
template<class T>
using sequence_of = range<input_iterator<T>>;
Wait, that's it? Nice, those types compose well!
And barring errors, we are done.
Your code now would take a sequence_of<int>, and they could pass a std::vector<int> or std::list<int> or whatever.
The input_iterator type-erasure type-erases any iterator down to getting a T via *, ==, copy, and ++ advance, which is enough for a for(:) loop.
The range<input_iterator<int>> will accept any iterable range (including containers) whose iterators can be converted to an input_iterator<int>.
The downside? We just introduced a bunch of overhead. Each method goes through virtual dispatch, from ++ to * to ==.
This is (roughly) what generics do -- they type-erase down to the requirements you give it in the generic clause. This means they are working with abstract objects, not concrete objects, so they unavoidably suffer performance penalties of this indirection.
C++ templates can be used to generate type erasure, and there are even tools (boost has some) to make it easier. What I did above is a half-assed manual one. Similar techniques are used in std::function<R(Args...)>, which type-erases down to (conceptually) {copy, call with (Args...) returning R, destroy} (plus some incidentals).
live example.
(The code above freely uses C++14.)
So the C++ equivalent Log is:
struct Log {
virtual void add(sequence_of<int>) = 0;
virtual ~Log() {}
};
Now, the type erasure code above is a bit ugly. To be fair, I just implemented a language feature in C++ without direct language support for it.
I've seen some proposals to make type erasure easier in C++. I do not know the status of those proposals.
If you want to do your own, here is an "easy" way to do type erasure in 3 steps:
First, determine what operations you want to erase. Write the equivalent of input_iterator<T> -- give it a bunch of methods and operators that do what you want. Be sparse. Call this the "external type". Ideally nothing in this type is virtual, and it should be a Regular or Semi-regular type (ie, it should behave value-like, or move-only-value-like). Don't implement anything but the interface yet.
Second, write an inner class erase. It provides a pure-virtual interface to a set of functions that could provide what you need in your external type.
Store a unique_ptr<erase> pimpl; within the external type. Forward the methods you expose in the external type to the pimpl;.
Third, write an inner template<class X> class impl<X>:erase. It stores a variable X x;, and it implements everything in erase by interacting with X. It should be constructable from an X (with optional perfect forwarding).
You then create a perfect forwarding constructor for the external type that creates its pimpl via a new impl<X>(whatever). Ideally it should check that its argument is a valid one via SFINAE techniques, but that is just a qualify of implementation issue.
Now the external type "erases" the type of any object it is constructed from "down to" the operations you exposed.
Now, for your actual problem, I'd write array_view or steal std::experimental::array_view, and restrict my input to be any kind of contiguous buffer of data of that type. This is more performant, and accepting any sequence is over engineering unless you really need it.
Consider the following example: http://play.golang.org/p/eAot_sVwND
package main
import "fmt"
type Incrementor interface {
Increment()
}
type Counter struct {
i int
Incrementor
}
func (c *Counter) Increment(){
c.i++
}
func main() {
var c Incrementor
c = &Counter{}
c.Increment()
fmt.Println(c)
}
Unfortunatelly I need to c = &Counter{} because Counter.Increment() implementation has a pointer receiver otherwise c.Increment() calls won't be able to modify c.x property:
func (c Counter) Increment(){
c.i++ // no errors, but now we increment c.x having a copy of c as context
}
How to make original implementation works without & on c = &Counter{}? In other words, how to avoid the need for the pointer receiver on C.Increment implementation at all?
This is just a nit, but I think that maybe a pointer is not necessary to do that in Go.
This is just a nit, but I think that maybe a pointer is not necessary to do that in Go.
Considering that Go uses to pass everything by value, a pointer receiver is the natural way to achieve what you want.
This is supported by the Go FAQ:
First, and most important, does the method need to modify the receiver? If it does, the receiver must be a pointer.
You would find a similar conclusion in "Things I Wish Someone Had Told Me About Golang: pointers"
You could consider defining an NewCounter function that encapsulates the initialization of your type (or some 3rd party) and returns a *Counter. Usage could look something like this:
func main() {
c := NewCounter()
c.Increment()
fmt.Println(c)
}
I often need to pass invalid location to functions that optionally can use location (eg. RTS unit action). But this does not compile:
public abstract void CastSpell(Spell spell, Vector3 targetLocation = null);
So how can I make a proper invaid Vector3 to determine invalid/"don't care" locations? I've seen things like vector with -999999 coordinates - but that's a nasty trick that might cause bugs (eg. on huge maps).
I had a similar problem in the past, I found there was two solutions. The first solution was to create a wrapper for the class.
Class Vector3Wrapper
{
Vector3 vector;
}
Then I would simply set the Vector3Wrapper to null then if it wasnt null access its vector. A better method would be making it a Nullable type. A example is below.
http://unitypatterns.com/nullable-types/
public class Character : MonoBehaviour
{
//Notice the added "?"
Vector3? targetPosition;
void MoveTowardsTargetPosition()
{
//First, check if the variable has been assigned a value
if (targetPosition.HasValue)
{
//move towards targetPosition.Value
}
else
{
//targetPosition.Value is invalid! Don't use it!
}
}
I'm trying to represent a human wearing glasses near a window when a nearby explosion occurs. main is a sketch of what should be done during the explosion. Something should gather up a list of objects in proximity of the explosion and do specific things (such as shattering or melting) for each of them. The glass and window shatter as expected, but for some reason the human also shatters. Why?
package main
import "fmt"
type Human struct { Glasses }
type Glasses struct {}
type Shatterable interface { shatter() }
func (g Glasses) shatter() {}
type Window struct {}
func (w Window) shatter() {}
func main() {
h := Human{Glasses{}}
objectsInProximity := []interface{}{h,h.Glasses,Window{}}
for _,o := range objectsInProximity {
shatter(o)
}
}
func shatter(i interface{}) {
s, ok := i.(Shatterable)
if ok {
fmt.Printf("shattering a %T\n", s)
s.shatter()
}
}
$ go run a.go
shattering a main.Human
shattering a main.Glasses
shattering a main.Window
As mentioned in this thread:
We're talking about anonymous fields of a struct
(http://golang.org/ref/spec#Struct_types).
(modified version, as the term superset is confusing)
A struct with an anonymous field satisfies every interface with all the interface methods declared by the anonymous field or the struct itself.
type Human struct { Glasses }
Since Glasses can be shattered, Human also satisfy the same interface.
Note: embedding anonymous field in a struct is the closest to "inheritance", even though the answer to "Golang: what's the point of interfaces when you have multiple inheritance" reminds us that:
Go doesn't have inheritance.
If Man 'extended' Human (by having it as an anonymous field), any method that used Human as an argument, would not be able to take Man as an argument.
(That means here Human extends... Glasses?! That might show some kind of design imperfection)
I explained before in "If struct A is embedded in B, can methods on A access method and fields of B?" that this isn't true sub-typing.
Interfaces enable functions to have a 'placeholder' parameter which can take different structs as an argument.
Here, if Human isn't supposed to be shattered, it shouldn't include the anonymous field Glasses.
(note: this is related to Usage preference between a struct and a class in D language but for a more specific use case)
When writing a D interface to, say, C++ code, SWIG and others do something like this:
class A{
private _A*ptr;//defined as extern(C) elsewhere
this(){ptr=_A_new();}//ditto
this(string s){ptr=_A_new(s);} //ditto
~this(){_A_delete(ptr);} //ditto
void fun(){_A_fun(ptr);}
}
Let's assume no inheritance is needed.
My question is: wouldn't it be preferable to use a struct instead of a class for this?
The pros being:
1) efficiency (stack allocation)
2) ease-of-use (no need to write new everywhere, eg: auto a=A(B(1),C(2)) vs auto a=new A(new B(1),new C(2)) )?
The cons being:
require additional field is_own to handle aliasing via postblit.
What would be the best way to do so?
Is there anything else to worry about?
Here's an attempt:
struct A{
private _A*ptr;
bool is_own;//required for postblit
static A opCall(){//cannot write this() for struct
A a;
a.ptr=_A_new();
a.is_own=true;
return a;
}
this(string s){ptr=_A_new(s); is_own=true;}
~this(){if(is_own) _A_delete(ptr);}
void fun(){_A_fun(ptr);}
this(this){//postblit;
//shallow copy: I don't want to call the C++ copy constructor (expensive or unknown semantics)
is_own=false; //to avoid _A_delete(ptr)
}
}
Note the postblit is necessary for cases when calling functions such as:
myfun(A a){}
I suggest that you read this page. The only functions on C++ classes that you can call in D are virtual functions. That means that
D cannot call C++ special member functions, and vice versa. These include constructors, destructors, conversion operators, operator overloading, and allocators.
And when you declare a C++ class in D, you use an extern(C++) interface. So, your class/struct would look like this
extern(C++) interface A
{
void fun();
}
However, you'd need another extern(C++) function to allocate any objects of type A, since it's C++ code that has to do that as the D code doesn't have access to any of the constructors. You'd also need a way to pass it back to C++ code to be deleted when you're done with it.
Now, if you want to wrap that interface in a type which is going to call the extern(C++) function to construct it and the extern(C++) function to delete it (so that you don't have to worry about doing that manually), then whether you use a class or struct depends entirely on what you're trying to do with it.
A class would be a reference type, which mirrors what the C++ class actually is. So, passing it around would work without you having to do anything special. But if you wanted a guarantee that the wrapped C++ object was freed, you'd have to do so manually, because there's no guarantee that the D class' finalizer would ever be run (and presumably, that's where you'd put the code for calling the C++ function to delete the C++ object). You'd have to either use clear (which will actually be renamed to destroy in the next release of the compiler - dmd 2.060) to destroy the D object (i.e. call its finalizer and handle the destruction of any of its member variables which are value types), or you'd have to call a function on the D object which called the C++ function to delete the C++ object. e.g.
extern(C++) interface A
{
void fun();
}
extern(C++) A createA();
extern(C++) void deleteA(A a);
class Wrapper
{
public:
this()
{
_a = createA();
}
~this()
{
deleteA(_a);
}
auto opDispatch(string name, Args...)(Args args)
{
return mixin("_a." ~ name ~ "(args)");
}
private:
A _a;
}
void main()
{
auto wrapped = new Wrapper();
//do stuff...
//current
clear(wrapped);
//starting with dmd 2.060
//destroy(wrapped);
}
But that does have the downside that if you don't call clear/destroy, and the garbage collector never collects your wrapper object, deleteA will never be called on the C++ object. That may or may not matter. It depends on whether the C++ object really needs its destructor to be called before the program terminates or whether it can just let its memory return to the OS (without its destructor being called) when the program terminates if the GC never needs to collect the wrapper object.
If you want deterministic destruction, then you need a struct. That means that you'll need to worry about making the struct into a reference type. Otherwise, if it gets copied, when one of them is destroyed, the C++ object will be deleted, and the other struct will point to garbage (which it will then try and delete when it gets destroyed). To solve that, you could use std.typecons.RefCounted. Then you get something like
extern(C++) interface A
{
void fun();
}
extern(C++) A createA();
extern(C++) void deleteA(A a);
struct Wrapper
{
public:
static Wrapper opCall()
{
Wrapper retval;
retval._a = createA();
return retval;
}
~this()
{
if(_a !is null)
{
deleteA(_a);
_a = null;
}
}
auto opDispatch(string name, Args...)(Args args)
{
return mixin("_a." ~ name ~ "(args)");
}
private:
A _a;
}
void main()
{
auto wrapped = RefCounted!Wrapper();
//do stuff...
}
You could also define the wrapper so that it has the ref-counting logic in it and avoid RefCounted, but that would definitely be more complicated.
Regardless, I would definitely advise against your suggestion of using a bool to mark whether the wrapper owns the C++ object or not, because if the original wrapper object gets destroyed before all of the copies do, then your copies will point to garbage.
Another option if you did want the C++ object's copy constructor to be used (and therefore treat the C++ object as a value type) would be to add an extern(C++) function which took the C++ object and returned a copy of it and then use it in a postblit.
extern(C++) A copyA(A a);
this(this)
{
if(_a !is null)
_a = copyA(a);
}
Hopefully that makes things clear enough.