Interface inheritance and the new keyword - c#

I want:
public interface IBase
{
MyObject Property1 { get; set; }
}
public interface IBaseSub<T> : IBase
{
new T Property1 { get; set; }
}
public class MyClass : IBaseSub<YourObject>
{
public YourObject Property1 { get; set; }
}
But this doesn't compile. It gives the error:
//This class must implement the interface member IBase.Property1
Can anyone shed some light on this? I thought it should work..
Thanks

IBaseSub<T> requires IBase. I say "requires" because it more accurately reflects the practical implications than to say it "inherits" IBase, which implies overriding and other things that simply don't happen with interfaces. A class which implements IBaseSub<T> can actually be said to implement both, like so:
public class MyClass : IBase, IBaseSub<YourObject>
Going back to what I said about inheritance - there is no such thing with interfaces, which means just because both interfaces have a property with the same name, the derived one isn't overriding or hiding the base one. It means that your class must now literally implement two properties with the same name to fulfill both contracts. You can do this with explicit implementation:
public class MyClass : IBase, IBaseSub<YourObject>
{
public YourObject Property1 { get; set; }
MyObject IBase.Property1 { get; set; }
}

You need to implement the properties from both IBase and IBaseSub<YourObject>, since the latter expands on the former.
Using new in IBaseSub<T> does not let you "off the hook" regarding the necessity to have a MyObject Property1 { get; set; }. It simply allows you to declare another property named Property1 that implementors of IBaseSub<T> must have.
Since you cannot have two properties with the same name in MyClass, you will be forced to implement at least one of them explicitly:
public class MyClass : IBaseSub<YourObject>
{
MyObject IBase.Property1 { get; set; }
public YourObject Property1 { get; set; }
}

Related

Change instance of abstract class that use generics

I am trying to replace derived instances in base class. It works for animals (simple usage of abstract class), but not with generics. The error is in SomeMethod. Is there any clean solution?
EDIT: With help of another interface it is truly doable. Code that is commented with [S] is solution for my original question.
public abstract class Animal
{
public void Feed()
{
}
}
public class Tiger:Animal
{
}
public class Dog : Animal
{
}
public class Consumer
{
public Tiger Tiger { get; set; }
public Dog Dog { get; set; }
public Animal FavoriteAnimal { get; set; }
void SomeMethod()
{
// This is fine
FavoriteAnimal = Tiger;
FavoriteAnimal = Dog;
FavoriteAnimal.Feed();
//Also fine
int numberOfDogs = PlaceForDogs.CountAnimals();
int numberOfTigers = PlaceForTigers.CountAnimals();
//[S] This is doable now
FavoritePlaceForAnimals = PlaceForDogs;//[S] no more ERROR
int numberOfAnimalsOnMyFavoritPlace = FavoritePlaceForAnimals.CountAnimals(); // No error, but I do not get here...
}
public PlaceForDogs PlaceForDogs { get; set; } = new PlaceForDogs();
public PlaceForTigers PlaceForTigers { get; set; } = new PlaceForTigers();
//public PlaceForAnimals<Animal> FavoritePlaceForAnimals { get; set; }
//[S] favorite place is of type IPlaceForAnimals instead of PlaceForAnimals
public IPlaceForAnimals FavoritePlaceForAnimals { get; set; }
}
//[S]new interface
public interface IPlaceForAnimals
{
int CountAnimals();
}
//[S]abstract class implements the interface
public abstract class PlaceForAnimals<T>:IPlaceForAnimals where T : Animal
{
public List<T> Animals { get; set; }
public int CountAnimals()
{
//special counting using properties from Animal class
return 0;
}
}
A PlaceForAnimals<Dog> is not a PlaceForAnimals<Animal> (for purposes of assigning it that type), as it could not hold a tiger (while the original could).
The assignment is simply not legal without covariance. If you want to access certain methods you could have the base class implement a non-generic interface and make FavoritePlaceForAnimals be of that type.
The generic is wrapping a common set of functionality around a certain data type. Like List<int> functions the same as List<string>, it just gives you different data when you access it.
You could use a generic in the sense that your PlaceForAnimals<T> could have some defined behavior, but wrapped around a generic object like, say a Dog. But because it is just a wrapper around some functionality, it doesn't behave the same way as an inherited class like you have with your Animal superclass.
Inheritance lets you interchange data types, generics do not.

C# Properties in interfaces & abstract classes

I was just coding a simple C# interface, and I put a property in it without thinking it through too far. For example:
public interface IMyInterface
{
string Name { get; set; }
object[][] Data { get; set;
}
I realized that I'm a little confused with properties when applied to interfaces and abstract base classes. In a normal class, this syntax would generate the accessor and mutator for a hidden string member that it generated behind the scenes.
Interfaces shouldn't be able to have data members. So, does this syntax do something different in that case?
What about for abstract classes? If I put this same syntax in the abstract base and the derived class, would both end up with a hidden member?
Interfaces shouldn't be able to have data members.
Those are properties, and those are allowed:
An interface contains only the signatures of methods, properties, events or indexers.
See also c# properties on Interface.
As for your second question:
If I put this same syntax in the abstract base and the derived class, would both end up with a hidden member?
Yes. You can prevent that by marking the property virtual on the base class and override on the derived class.
The property declaration in the interface is completely separate from the implementation. Thus you can implement it using automatic properties
private class MyImpl : IMyInterface
{
public string Name { get; set; }
public object[][] Data { get; set; }
}
or declare your own backing field
private class MyImplBacked : IMyInterface
{
private string _name;
public string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}
public object[][] Data { get; set; }
}
Same scenario in abstract classes
public abstract class MyAbstractClass
{
public abstract string Name { get; set; }
public abstract object[][] Data { get; set; }
}
private class MyImpl : MyAbstractClass
{
public override string Name { get; set; }
public override object[][] Data { get; set; }
}
private class MyImplBacked : MyAbstractClass
{
private string _name;
public override string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}
public override object[][] Data { get; set; }
}
Interfaces shouldn't be able to have data members. So, does this syntax do something different in that case?
Technically it's not a data member - it's a get/set method pair that has an underlying data member. There's no implementation.
What about for abstract classes? If I put this same syntax in the abstract base and the derived class, would both end up with a hidden member?
If the class is abstract and the property is virtual then yes, you will be overriding an auto-implemented property with another auto-implemented property (which is pointless).
If the class is abstract and the property is NOT virtual then you still have two implementations, but the base class is hiding the parent implementation rather than overriding it (which is still pointless if they're both auto-implemented).
If the property is abstract then the abstract class won't have an implementation. You'll have to implement the get/set in your concrete class (which could be auto-implemented bot doesn't have to be).

How should I abstract a collection of objects owned by another object?

In a system for managing vocational training, I have a CourseBase abstract class, which I decided on using in favour of an ICourse interface because I'd prefer to avoid duplicating implementation code for all classes derived from the hypothetical, base Course entity. Each course has a list if subjects, with any subject defined by a SubjectBase abstract class. So, I have e.g.
public abstract class CourseBase : BaseObject
{
public IEnumerable<SubjectBase> Subjects
{
get { return new List<SubjectBase>(); }
}
}
public abstract class SubjectBase
{
public string Name { get; set; }
public string Description { get; set; }
public int ValidityPeriod { get; set; }
}
Now I want to add a concrete class, LocalCourse, which contains a collection of LocalCourseSubject objects, but because I'm not using an interface for CourseBase, I lose out on covariance, and I need to hide the abstract base's Subjects property with my new:
public class LocalCourse: CourseBase
{
public IEnumerable<LocalCourseSubject> Subjects
{
get { throw new NotImplementedException(); }
}
}
I'm sure I'm missing something very obvious here from an OO point of view, but the only solutions I can see are:
Completely omit Subjects from the abstract base, and only add a specifically typed collection property to derived classes.
Implement an interface such as ISubjectCollectionOwner in the abstract base as well as concrete classes.
Please excuse my dimness here, it's been a while since I've had the pleasure of encountering a design issue like this.
Why just not introduce a generic interface to abstract a Course? Sorry if I missed something obvious
public interface ICourse<TSubject>
{
IEnumerable<TSubject> Subjects { get; }
}
public abstract class CourseBase<TSubject>
: BaseObject,
ICourse<TSubject>
{
public IEnumerable<TSubject> Subjects
{
get { return new List<TSubject>(); }
}
}
public class LocalCourse
: CourseBase<LocalCourseSubject>
{
}
If Subject is a vital part of Course entity you should keep it within both ICourse and CourseBase as well, otherwise I would suggects abstracting it by ISubjectAware interface
Can't you just do this:
public abstract class CourseBase<T> where T : SubjectBase
{
public virtual IEnumerable<T> Subjects
{
get { return new List<T>(); }
}
}
public abstract class SubjectBase
{
public string Name { get; set; }
public string Description { get; set; }
public int ValidityPeriod { get; set; }
}
public class LocalCourse : CourseBase<LocalCourseSubject>
{
public override IEnumerable<LocalCourseSubject> Subjects
{
get { throw new NotImplementedException(); }
}
}
I think that would accomplish your short term goal, at any rate, assuming that the general pattern is that each CourseBase inheritor will have a collection of the same type of SubjectBase inheritor. But, if that is the case, this seems like a parallel inheritance hierarchy, which can sometimes be a code smell (not saying that it necessarily is -- I don't know all the details of the domain you're modeling).

In C# is there no way to make a class define a field using an Interface or abstract class?

I would like to force a set of classes to define three fields (of type string).
In an abstract class, I get that fields cannot be abstract and in an interface, I get an error saying that an interface cannot contain a field.
Is there no way to do this or am I not understanding this correctly? I'd rather not use methods because for some weird reason, the parentheses annoy me.
You can use properties for that:
interface MyInterface {
string Prop1 { get; set; }
string Prop2 { get; set; }
string Prop3 { get; set; }
}
Interface or abstract members force derived classes to provide code.
Fields don't have code.
You should use a property, which can be used like a field, but has code.
You can use Properties instead of fields:
// works similarly for Interfaces too
abstract class MyAbstractClass { public virtual string MyProperty1 { get; set; } }
class MyConcreteClass : MyAbstractClass { }
Then you can access MyProperty1 from any instance derived from MyAbstractClass:
MyAbstractClass obj1 = new MyConcreteClass;
obj1.MyProperty1 = "abcd";
Like everyone else says, use properties instead of fields, but you can do something like I interpreted in the comments as follows for read-only members:
abstract public class Base
{
abstract public string Foo { get; }
abstract public string Bar { get; }
abstract public string Baz { get; }
}
public class Derived : Base
{
public override string Foo { get { return "foo"; } }
public override string Bar { get { return "bar"; } }
public override string Baz { get { return "baz"; } }
}
If you want the fields to be modifiable later, you'll have to either use automatic properties or declare concrete backing fields and getter/setter pairs for each property.

Implementing interface C#

I'm not new to C#, but I have found a behavior that is a little puzzling.
I have an interface
public interface IApplicationPage
{
Person ThePerson { get; set; }
Application Application { get; set; }
}
I implement the interface on a page
public partial class tripapplication2 : System.Web.UI.Page, IApplicationPage
{
Person IApplicationPage.ThePerson { get; set; }
Application IApplicationPage.IApplicationPage.Application { get; set; }
}
However, when I attempt to reference ThePerson in the page itself I need to jump through hoops. For example.
1) ThePerson.Birthday
Gives an error saying "The name 'ThePerson' does not exist in the current context."
2) ((IMissionTripApplicationPage)this).ThePerson.Birthday
This works, but it looks awful.
Is there a better way to reference the implemented properties?
It looks like you left a line out in your sample. I believe the ThePerson line in the implementation should read
Person IApplicationPage.ThePerson { get; set; }
This type of implementation is known as an explicit interface implementation. This means the member will only be viewable when the object is seen through a reference of the interface type.
If you want the member to be viewable through a concrete type reference, make it public and remove the explicit implementation
public Person ThePerson { get; set; }
Implement them as public properties:
public partial class tripapplication2 : System.Web.UI.Page, IApplicationPage
{
public Person ThePerson { get; set; }
public Application IApplicationPage.Application { get; set; }
}
Edit
Question now edited to show these were implemented originally as explicit. So, I should restate mine as implement them as public rather than explicit implementations of the properties.

Categories

Resources