Groups | Blog | Home
all groups > vj# > may 2004 >

vj# : Interface implementation in J#


Sameeksha
5/7/2004 12:26:09 AM
I've one C# sample which contains a class
public class CustomersList : CollectionBase, IBindingList {...
which does not implement ALL methods of interface IBindingList. It compiles properl

I've converted same class to J# with same method implementations.
The class description i
public class CustomersList extends CollectionBase implements IbindingLis

It gives the foll compilation error

'IBindingList_Doc.CustomersList' must be declared 'abstract' or these
methods must be implemented:
System.Collections.IList.Contains(System.Object),
System.Collections.ICollection.CopyT
(System.Array,int),
System.Collections.ICollection.CopyT
(System.Array,int).

In C# file also these methods are not
implemented, but in J# it’s giving
error for lots of such methods

When I searched for interface
implementation on the internet, I got
one similar example, it was in C#,
where it was explained that methods
of the IList are implemented in the
CollectionBase class, and so even if
they are not implemented in the
derived, user defined class, there
will be no compilation error. This
explains why there is no error in C#
file, but why the same logic doesn’t
work for J#

One more reference in a related
discussion on the net was as follows

C# does search the base class list
for interface implementations,
whereas J# should not according to
JLS2
Is that the reason why we get
Amit.vjc NO[at]SPAM online.microsoft.com
5/10/2004 1:42:48 PM
Hi,
Can you post the exact C# sample that works for you?
Then we can help you in writing corresponding J# sample for you.

--------------------
[quoted text, click to view]
public class CustomersList : CollectionBase, IBindingList {...}
which does not implement ALL methods of interface IBindingList. It compiles
properly

I've converted same class to J# with same method implementations.
The class description is
public class CustomersList extends CollectionBase implements IbindingList

It gives the foll compilation error.

'IBindingList_Doc.CustomersList' must be declared 'abstract' or these
methods must be implemented:
System.Collections.IList.Contains(System.Object),
System.Collections.ICollection.CopyTo
(System.Array,int),
System.Collections.ICollection.CopyTo
(System.Array,int).

In C# file also these methods are not
implemented, but in J# it’s giving
error for lots of such methods.

When I searched for interface
implementation on the internet, I got
one similar example, it was in C#,
where it was explained that methods
of the IList are implemented in the
CollectionBase class, and so even if
they are not implemented in the
derived, user defined class, there
will be no compilation error. This
explains why there is no error in C#
file, but why the same logic doesn’t
work for J#?

One more reference in a related
discussion on the net was as follows:

C# does search the base class list
for interface implementations,
whereas J# should not according to
JLS2.
Is that the reason why we get
errors in J# file. What would be the probable solution for this problem?
[quoted text, click to view]
Sameeksha
5/11/2004 10:46:05 PM
Hi
Thanks for your cooperation
Here is the complete C# code that works fin

using System
using System.Drawing
using System.Collections
using System.ComponentModel
using System.Windows.Forms
using System.Data
using System.IO

namespace IBindingList_Do


// sample for IEditableObjec
//<snippet1
public class Customer : IEditableObject


struct CustomerData

internal string id
internal string firstName
internal string lastName


private CustomersList parent
private CustomerData custData;
private CustomerData backupData;
private bool inTxn = false

// Implements IEditableObjec
void IEditableObject.BeginEdit()

Console.WriteLine("Start BeginEdit")
if (!inTxn)

this.backupData = custData
inTxn = true
Console.WriteLine("BeginEdit - " + this.backupData.lastName)

Console.WriteLine("End BeginEdit")


void IEditableObject.CancelEdit()

Console.WriteLine("Start CancelEdit")
if (inTxn)

this.custData = backupData
inTxn = false
Console.WriteLine("CancelEdit - " + this.custData.lastName)

Console.WriteLine("End CancelEdit")


void IEditableObject.EndEdit()

Console.WriteLine("Start EndEdit" + this.custData.id + this.custData.lastName)
if (inTxn)

backupData = new CustomerData()
inTxn = false
Console.WriteLine("Done EndEdit - " + this.custData.id + this.custData.lastName)

Console.WriteLine("End EndEdit")


public Customer(string ID) : base()

this.custData = new CustomerData()
this.custData.id = ID
this.custData.firstName = ""
this.custData.lastName = ""


public string ID

get

return this.custData.id



public string FirstName

get

return this.custData.firstName

set

this.custData.firstName = value



public string LastName

get

return this.custData.lastName

set

this.custData.lastName = value



internal CustomersList Parent

get

return parent

set

parent = value



private void OnCustomerChanged()

if (!inTxn && Parent != null)

Parent.CustomerChanged(this)


//</snippet1
public override string ToString()

StringWriter sb = new StringWriter()
sb.Write(this.FirstName)
sb.Write(" ")
sb.Write(this.LastName)
return sb.ToString()
}

// end of Customer class - sample for IEditableObjec

// sample for IBindingLis
//<snippet2
public class CustomersList : CollectionBase, IBindingLis


private ListChangedEventArgs resetEvent = new ListChangedEventArgs(ListChangedType.Reset, -1)
private ListChangedEventHandler onListChanged

public void LoadCustomers()

IList l = (IList)this
l.Add(ReadCustomer1())
l.Add(ReadCustomer2())
OnListChanged(resetEvent)


public Customer this[int index]

get

return (Customer)(List[index])

set

List[index] = value



public int Add (Customer value)

return List.Add(value)


public Customer AddNew()

return (Customer)((IBindingList)this).AddNew()


public void Remove (Customer value)

List.Remove(value)



protected virtual void OnListChanged(ListChangedEventArgs ev)

if (onListChanged != null)

onListChanged(this, ev)




protected override void OnClear()

foreach (Customer c in List)

c.Parent = null



protected override void OnClearComplete()

OnListChanged(resetEvent)


protected override void OnInsertComplete(int index, object value)

Customer c = (Customer)value
c.Parent = this
OnListChanged(new ListChangedEventArgs(ListChangedType.ItemAdded, index))


protected override void OnRemoveComplete(int index, object value)

Customer c = (Customer)value
c.Parent = this
OnListChanged(new ListChangedEventArgs(ListChangedType.ItemDeleted, index))
}

protected override void OnSetComplete(int index, object oldValue, object newValue)
{
if (oldValue != newValue)
{

Customer oldcust = (Customer)oldValue;
Customer newcust = (Customer)newValue;

oldcust.Parent = null;
newcust.Parent = this;


OnListChanged(new ListChangedEventArgs(ListChangedType.ItemAdded, index));
}
}

// Called by Customer when it changes.
internal void CustomerChanged(Customer cust)
{

int index = List.IndexOf(cust);

OnListChanged(new ListChangedEventArgs(ListChangedType.ItemChanged, index));
}


// Implements IBindingList.
bool IBindingList.AllowEdit
{
get { return true ; }
}

bool IBindingList.AllowNew
{
get { return true ; }
}

bool IBindingList.AllowRemove
{
get { return true ; }
}

bool IBindingList.SupportsChangeNotification
{
get { return true ; }
}

bool IBindingList.SupportsSearching
{
get { return false ; }
}

bool IBindingList.SupportsSorting
{
get { return false ; }
}


// Events.
public event ListChangedEventHandler ListChanged
{
add
{
onListChanged += value;
}
remove
{
onListChanged -= value;
}
}

// Methods.
object IBindingList.AddNew()
{
Customer c = new Customer(this.Count.ToString());
List.Add(c);
return c;
}


// Unsupported properties.
bool IBindingList.IsSorted
{
get { throw new NotSupportedException(); }
}

ListSortDirection IBindingList.SortDirection
{
get { throw new NotSupportedException(); }
}


PropertyDescriptor IBindingList.SortProperty
{
get { throw new NotSupportedException(); }
}


// Unsupported Methods.
void IBindingList.AddIndex(PropertyDescriptor property)
{
throw new NotSupportedException();
}

void IBindingList.ApplySort(PropertyDescriptor property, ListSortDirection direction)
{
throw new NotSupportedException();
}

int IBindingList.Find(PropertyDescriptor property, object key)
{
throw new NotSupportedException();
}

void IBindingList.RemoveIndex(PropertyDescriptor property)
{
throw new NotSupportedException();
}

void IBindingList.RemoveSort()
{
throw new NotSupportedException();
}

// Worker functions to populate the list with data.
private static Customer ReadCustomer1()
{
Customer cust = new Customer("536-45-1245");
cust.FirstName = "Jo";
cust.LastName = "Brown";
return cust;
}

private static Customer ReadCustomer2()
{
Customer cust = new Customer("246-12-5645");
cust.FirstName = "Robert";
cust.LastName = "Brown";
return cust;
}


//</snippet2>


}
}
Amit.vjc NO[at]SPAM online.microsoft.com
5/13/2004 1:11:33 PM
This is a bug in VJ#. We are fixing it in the next version of VJ#.

--------------------
[quoted text, click to view]
Thanks for your cooperation.
Here is the complete C# code that works fine

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.IO;

namespace IBindingList_Doc
{

// sample for IEditableObject
//<snippet1>
public class Customer : IEditableObject
{

struct CustomerData
{
internal string id ;
internal string firstName ;
internal string lastName ;
}

private CustomersList parent;
private CustomerData custData;
private CustomerData backupData;
private bool inTxn = false;

// Implements IEditableObject
void IEditableObject.BeginEdit()
{
Console.WriteLine("Start BeginEdit");
if (!inTxn)
{
this.backupData = custData;
inTxn = true;
Console.WriteLine("BeginEdit - " + this.backupData.lastName);
}
Console.WriteLine("End BeginEdit");
}

void IEditableObject.CancelEdit()
{
Console.WriteLine("Start CancelEdit");
if (inTxn)
{
this.custData = backupData;
inTxn = false;
Console.WriteLine("CancelEdit - " + this.custData.lastName);
}
Console.WriteLine("End CancelEdit");
}

void IEditableObject.EndEdit()
{
Console.WriteLine("Start EndEdit" + this.custData.id +
this.custData.lastName);
if (inTxn)
{
backupData = new CustomerData();
inTxn = false;
Console.WriteLine("Done EndEdit - " + this.custData.id +
this.custData.lastName);
}
Console.WriteLine("End EndEdit");
}

public Customer(string ID) : base()
{
this.custData = new CustomerData();
this.custData.id = ID;
this.custData.firstName = "";
this.custData.lastName = "";
}

public string ID
{
get
{
return this.custData.id;
}
}

public string FirstName
{
get
{
return this.custData.firstName;
}
set
{
this.custData.firstName = value;
}
}

public string LastName
{
get
{
return this.custData.lastName;
}
set
{
this.custData.lastName = value;
}
}

internal CustomersList Parent
{
get
{
return parent;
}
set
{
parent = value ;
}
}

private void OnCustomerChanged()
{
if (!inTxn && Parent != null)
{
Parent.CustomerChanged(this);
}
}
//</snippet1>
public override string ToString()
{
StringWriter sb = new StringWriter();
sb.Write(this.FirstName);
sb.Write(" ");
sb.Write(this.LastName);
return sb.ToString();
}
}
// end of Customer class - sample for IEditableObject

// sample for IBindingList
//<snippet2>
public class CustomersList : CollectionBase, IBindingList
{

private ListChangedEventArgs resetEvent = new
ListChangedEventArgs(ListChangedType.Reset, -1);
private ListChangedEventHandler onListChanged;

public void LoadCustomers()
{
IList l = (IList)this;
l.Add(ReadCustomer1());
l.Add(ReadCustomer2());
OnListChanged(resetEvent);
}

public Customer this[int index]
{
get
{
return (Customer)(List[index]);
}
set
{
List[index] = value;
}
}

public int Add (Customer value)
{
return List.Add(value);
}

public Customer AddNew()
{
return (Customer)((IBindingList)this).AddNew();
}

public void Remove (Customer value)
{
List.Remove(value);
}


protected virtual void OnListChanged(ListChangedEventArgs ev)
{
if (onListChanged != null)
{
onListChanged(this, ev);
}
}


protected override void OnClear()
{
foreach (Customer c in List)
{
c.Parent = null;
}
}

protected override void OnClearComplete()
{
OnListChanged(resetEvent);
}

protected override void OnInsertComplete(int index, object value)
{
Customer c = (Customer)value;
c.Parent = this;
OnListChanged(new ListChangedEventArgs(ListChangedType.ItemAdded,
index));
}

protected override void OnRemoveComplete(int index, object value)
{
Customer c = (Customer)value;
c.Parent = this;
OnListChanged(new ListChangedEventArgs(ListChangedType.ItemDeleted,
index));
}

protected override void OnSetComplete(int index, object oldValue, object
newValue)
{
if (oldValue != newValue)
{

Customer oldcust = (Customer)oldValue;
Customer newcust = (Customer)newValue;

oldcust.Parent = null;
newcust.Parent = this;


OnListChanged(new ListChangedEventArgs(ListChangedType.ItemAdded,
index));
}
}

// Called by Customer when it changes.
internal void CustomerChanged(Customer cust)
{

int index = List.IndexOf(cust);

OnListChanged(new ListChangedEventArgs(ListChangedType.ItemChanged,
index));
}


// Implements IBindingList.
bool IBindingList.AllowEdit
{
get { return true ; }
}

bool IBindingList.AllowNew
{
get { return true ; }
}

bool IBindingList.AllowRemove
{
get { return true ; }
}

bool IBindingList.SupportsChangeNotification
{
get { return true ; }
}

bool IBindingList.SupportsSearching
{
get { return false ; }
}

bool IBindingList.SupportsSorting
{
get { return false ; }
}


// Events.
public event ListChangedEventHandler ListChanged
{
add
{
onListChanged += value;
}
remove
{
onListChanged -= value;
}
}

// Methods.
object IBindingList.AddNew()
{
Customer c = new Customer(this.Count.ToString());
List.Add(c);
return c;
}


George Birbilis [MVP J#] [9880]
5/27/2004 4:14:20 PM
[quoted text, click to view]

I'm quite sure Java can use the methods inherited from ancestor class if you
implement an interface at a descendent class that asks for these methods

for example the following one works using the default Java1.2 compiler
option included in JBuilder3

package untitled2;

interface X
{
public void test();
}

class MyClass1
//implements X
{
public void test(){
System.out.println("test");
}
}

class MyClass2
extends MyClass1
implements X
{

}

note MyClass1 doesn't implement X, but carries a method with the same
"signature" as the "test" method of interface X and MyClass2 implements X
just by extending MyClass1

the J# compiler should create correct method signatures in order to not have
such problems (this may fire in other situations as well, if the problem is
that the J# compiler doesn't generate proper method signatures according to
the Java language spec)

[quoted text, click to view]

for the time being, reimplement the methods required by the interface and
call into the ancestor using "super.xxx" syntax

e.g.

int xxx(){
return super.xxx();
}

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
George Birbilis <birbilis@kagi.com> [MVP J#] [9880]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ QuickTime VCL and ActiveX controls (for PowerPoint/VB/Delphi etc.)
+ Plugs VCL and ActiveX controls (InterProcess/Internet communication)
+ TransFormations, VB6 forms to ASP.net WebForms convertion
http://www.kagi.com/birbilis
+ Robotics
http://www.mech.upatras.gr/~robgroup
.........................................................................


AddThis Social Bookmark Button