HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

[vJass] extend 2 different interfaces

11-25-2007, 04:40 PM#1
zen87
just wondering how we can extend 2 different interfaces in a single struct?

Collapse JASS:
interface A
    integer x
endinterface

interface B
    integer y
endinterface

struct C extend <????>
  //so that wen can do this
    method SomeMethod takes nothing returns nothing
        .x = 123
        .y = 321
    endmethod
endstruct

11-25-2007, 04:52 PM#2
rain9441
Multiple inheritance isn't supported in vJass at this time. You cannot extend more than one struct or interface.
11-25-2007, 04:57 PM#3
cohadar
C++ freaks.
11-25-2007, 08:56 PM#4
Vexorian
Quote:
Originally Posted by cohadar
C++ freaks.
interface inheritance or whatever you call it is sane for multiple inheritance, afaik Java and C# allow multiple interfaces on implements.

Either way, this is unfortunately not going to happen, the reason is mostly that 8190 limit.

Imagine if extending multiple interfaces was supported, you would have to make both interfaces share ids, and then you would half each of the interfaces' (and childs') instance limits...
11-25-2007, 09:14 PM#5
cohadar
Quote:
Originally Posted by Vexorian
interface inheritance or whatever you call it is sane for multiple inheritance, afaik Java and C# allow multiple interfaces on implements.

Well thank you for telling me that, I really did not notice till now
Just in case someone might ask: multiple class inheritance is not the same as multiple interface implementation

You actually can make multiple interface implementations in JASS,
without the need to share Id's
(Think in the direction of virtual calls done with ExecuteFunc )
11-25-2007, 09:27 PM#6
Vexorian
Quote:
Just in case someone might ask: multiple class inheritance is not the same as multiple interface implementation
It's the same no matter how you call it, when the guy asks you about extending multiple interfaces he is not asking for "class inheritance".

Quote:
(Think in the direction of virtual calls done with ExecuteFunc )

Really, you need to share ids.
11-25-2007, 09:52 PM#7
PipeDream
They don't need to share because two different structs are different types. If you have strong typing, either directly or through typecasts, you can always specialize to one or the other struct. Specializing may mean duplicating code to run on two different sets of arrays.
If you want dynamic typing like virtual calls, then you do need to share. However you can specialize the sharing. For example as a user I would implement this by, where I need to store or pass the object dynamically, I create a third struct which is a tagged union of the two structs.

My personal bias is to leave this to the user and not implement dynamism beyond function pointers.

Edit: This brings interfaces inline with type classes. I like type classes.
11-25-2007, 10:03 PM#8
Vexorian
Sorry, but I thought of this for long, long months and I am still convinced you need to share ids.

The bad news is that someone is going to have to hand compile this to show me it works without sharing ids.

Collapse JASS:

interface A
    method close takes nothing returns nothing
endinterface

interface B
    method clear takes nothing returns nothing
endinterface

struct C extends A
    method close takes nothing returns nothing 
          call BJDebugMsg("C")
    endmethod
endstruct

struct D extends B
    method clear takes nothing returns nothing
          call BJDebugMsg("D")
    endmethod
endstruct

struct E extends A,B
    method close takes nothing returns nothing 
          call BJDebugMsg("E")
    endmethod

    method clear takes nothing returns nothing
          call BJDebugMsg("E'")
    endmethod
endstruct


function something takes A a, B b returns nothing
      call a.close()
      call b.clear()
endfunction

function something2 takes nothing returns nothing
 local C c = C.create()
 local D d = D.create()
 local E e = E.create()

     call something(c,d)
     call something(e,e)
     call something(e,d)

endmethod




Edit : I now understand what pipe says, but for some reason I think that duplicating code like crazy would be a worse trade off than sharing ids.

Edit II: I still think it would not be possible even with code duplication: let's add this to the equation:

Collapse JASS:
globals
    A array aV
    integer aN=0
    B array bV
    integer bN=0
endglobals

function doall takes nothing returns nothing
 local integer i=0
    loop
          exitwhen (i>=aN) or (i>=bN)
          call something(aV[i],bV[i])
          set i=i+1
    endloop

endfunction

function addA takes A a returns nothing
     set aV[aN] = a
     set aN=aN+1
endfunction

function addB takes B b returns nothing
     set bV[aN] = b
     set bN=bN+1
endfunction

function something3 takes nothing returns nothing
    call addA( C.create() )
    call addA( E.create() )
    call addA( C.create() )
    call addA( E.create() )
    call addA( C.create() )
    call addA( E.create() )

    call addB( E.create() )
    call addB( E.create() )
    call addB( D.create() )
    call addB( E.create() )
    call addB( E.create() )
    call addB( D.create() )
    call addB( E.create() )
    call addB( D.create() )
    call addB( D.create() )
    call doall()
function
11-25-2007, 10:14 PM#9
PipeDream
Collapse JASS:
function somethingCD takes C c, D d returns nothing
    call c.close()
    call d.close()
endfunction

function somethingEE takes E e, E e1 returns nothing
    call e.close()
    call e.clear()
endfunction

function somethingED takes E e, D d returns nothing
    call e.close()
    call d.clear()
endfunction

function something2 takes nothing returns nothing
    local C c = C.create()
    local D d = D.create()
    local E e = E.create()

    call somethingCD(c,d)
    call somethingEE(e,e)
    call somethingED(e,d)
endfunction

---
You would also like to sum interfaces so that you could write something along the lines of
Collapse JASS:
function someotherthing takes A B b

This really is type classes, but with out the hideous x<y> notation for explicit types we discussed in the polymorphism thread.

Reply to Edit II:
Storing variables like that is what I mean by dynamic typing. You can specialize the storage, and this is often in fact what you want, e.g. for constructing systems that store different types when you always know which type you want to store or retrieve. However when you really want to ask a question like "give me something which could be either of those two types" you need the tagged union the way interfaces are currently implemented. With an extra level of indirection you don't need to union at the bottom, so that only when you are physically unioning over a set of structs do you push on the instance limit. This reaches the minimum that you would need to hand code the same program semantics.

You can
Let the user specifically construct a struct to tag and store either
Collapse JASS:
globals
    constant integer UnionAB_is_A = 1
    constant integer UnionAB_is_B = 2
endglobals

struct UnionAB
    integer t
    struct A
    struct B

This deserves some sugar though, consider a tagged union type
Collapse JASS:
taggedunion UnionAB = UA A | UB B // or whatever syntax
This notation could be extended so that general structs can be built with it too:
Collapse JASS:
data GameEvent = StartLevel integer | HealUnits player real | NothingHappens 
Or you could write this in a more traditional way
Collapse JASS:
data GameEvent
    StartLevel integer
    HealUnits player real
    NothingHappens
enddata

Use might look like
Collapse JASS:
function NothingToSeeHere takes GameEvent e returns GameEvent
    if e.type == NothingHappens then // NothingHappens.type() ?
        return StartLevel.create(1)
    else
        return NothingHappens.create() // since there's only one possible instance of NothingHappens, this return an inlined constant
    endif
endfunction

Also, I think we still have a lot more storage to abuse before the instance limit will start to become a concern, although it is nice to be in a place where you never have to worry about it.
11-26-2007, 01:04 AM#10
zen87
wow... i though this is a yes and no question and it cames out pretty complicated answer >_<! anyway, thanks guys :D