I'm changing a class from public abstract AwesomeClass, to public sealed AwesomeClass. I've also added a new property. All existing members are unchanged. I know that this is a breaking change. Clients that have implemented AwesomeClass or relied on it being abstract via reflection will be broken.
My question is, will clients that have only used members of instances of AwesomeClass that I've provided, be broken (and if yes how)? None of the clients will have a dependency on any of my types that implemented AwesomeClass as they were all internal. I think not, but...
Here is the class before and after:
public abstract class AwesomeClass
{
public abstract Guid SuperGuid { get; set; }
public abstract int SuperInt { get; set; }
}
public sealed class AwesomeClass
{
public Guid SuperGuid { get; set; }
public int SuperInt { get; set; }
public int OtherSuperInt { get; set; }
}
You mean that when you have this:
public abstract class Foo
{
public string Bar;
}
void UpdateFooBar(Foo foo)
{
foo.Bar = "Updated";
}
And you change abstract class Foo to sealed class Foo, will UpdateFooBar(Foo foo) continue to work?
What kept you from trying? But yes, it will.
Related
I have a rather simple problem, but I can't find a proper solution anywhere. I would like to specify an abstract object CustomValues as property in my abstract parent class. However, the class inheriting from it should be able to use a more specific type as an object for this property CustomValues. At first I thought I would solve the problem by an interface, but unfortunately that didn't work out either. How do you do something like that, that it works?
public abstract class MyAbstract {
public abstract object CustomValues { get; set; }
}
public class MyImplementation : MyAbstract {
public override MySpecificClass CustomValues { get; set; }
}
This will throw me three errors:
Missing implementation for getter
Missing implementation for setter
Type missmatch between type object and MySpecificClass
The solution suggested in the comments would look something like this. (I'm assuming CustomValues should be a collection of something.)
public class MyClass<T>
{
public ICollection<T> CustomValues { get; set; }
}
Or to ensure CustomValues itself cannot be reassigned, but can be accessed and added to:
public class MyClass<T>
{
public ICollection<T> CustomValues { get; } = new List<T>();
}
I think your original thought that use an interface (+ generic) was at the correct direction. In general you might want to add type constraints as well.
public interface ICustomValues {
....
}
public class MySpecificClass : ICustomValues {
....
}
public abstract class MyAbstract<T> where T : ICustomValues {
public abstract T CustomValues {
get;
set;
}
}
public class MyImplementation: MyAbstract<MySpecificClass> {
public override MySpecificClass CustomValues { get; set; }
}
Thanks to you all guys. I found the solution by using a generic properly:
public abstract class MyAbstract<T> {
public abstract T CustomValues { get; set; }
}
public class MyImplementation : MyAbstract<MySpecificClass> {
public override MySpecificClass CustomValues { get; set; }
}
Is there any practial reason to create interface for abstract class? I encountered such thing:
public interface IEntity<T>
{
T Id { get; set; }
}
public abstract class BaseEntity {
}
public abstract class Entity<T> : BaseEntity, IEntity<T>
{
public virtual T Id { get; set; }
}
and i really don't understand what is the difference between that and this code, because IEntity is not a thing i whould use more than once:
public abstract class BaseEntity {
}
public abstract class Entity<T> : BaseEntity
{
public virtual T Id { get; set; }
}
Thanks!
Since the BaseEntity class does actually add any properties of methods, yes, it is completely different from the interface. The interface defines a property Id of type T, and that interface (contract) can be used in other locations in your application.
The base class as it is now, is useless IMHO.
A base class which would implement the interface for you is something that would be usable, like this:
public interface IEntity<T> {
T Id { get; set; }
}
public abstract class BaseEntity<T>: IEntity<T> {
public virtual T Id { get; set; }
}
public abstract class Entity<T> : BaseEntity<T> {
// No need to implement the Id property, we already have it inherited
}
Here is the same thing with correct answer that i wanted to know: c# Abstract Class implementing an Interface
Thanks everyone for help.
I'm creating a form to manage the reports of my application, the idea is that every report form inherits from this base form. My problem is that it contains several properties that HAVE to be assigned and i need to verify on every child form if I already called all, so... I'm wondering if there is a way to automatically make a call to all those properties.
This is part of the controller code:
public abstract partial class ReportsController()
{
public string Table{ get; set; }
public string Fields{ get; set; }
public string Condition{ get; set; }
public string Group{ get; set; }
public string Order{ get; set; }
public DataGridViewColumnCollection Columns{ get; set; }
public SortedList<string, string> ComboboxFields{ get; set; }
etc...
protected abstract void New();
protected abstract void Edit();
protected abstract void Print();
}
As you can see, methods are not a problem, they are abstract so they will have to be declared (and thanks to Resharper i will be warned if i missed one).
Child form:
public partial class frmReportGuards : ReportsController
{
public frmReportGuards()
{
code...
}
protected override void New()
{
code...
}
other methods...
}
And im looking for this:
public partial class frmReportGuards : ReportsController
{
public frmReportGuards()
{
//Auto assigned properties.
Table = "";
Fields = "";
Condition = "";
Group = "";
Order = "";
Columns = new DataGridViewColumnCollection();
ComboboxFields = new SortedList<string, string>();
}
protected override void New()
{
code...
}
other methods...
}
I don't know if I'm being senseless here :/ and I really need to get out of this doubt and if is possible... then simplify my work.
If your goal is to ensure that your properties are initialized to some default value, just add a constructor to ReportsController and set the properties there.
Now I understand, if you need to enforce implementation you should do it with abstract properties, inherited classes should implement then, and can be implemented with auto-properties:
public abstract class A
{
public abstract int MyProperty { get; set; }
}
public class B : A
{
public override int MyProperty { get; set; }
}
Short answer is not in C#5.0, in C#6.0 you have Auto-Property initializers, but I think that this is not what you are looking for.
Assuming you need a parameterless constructor, you can create an Init abstract method that is called from your base constructor and do a check if your initialization missed a property. There you can throw an exception or show a visual message indicating the failure.
So in base you do:
public abstract partial class ReportsController()
{
public ReportsController()
{
InitializeComponent();
//now your method
Init();
CheckProperties();
}
protected virtual void CheckProperties()
{
if(Table==null)
addVisualErrorMessage("Table property missing");
//and so on
}
protected abstract void Init();
}
But maybe you have to rethink your design and provide a single class with all the properties, so you can create an abstract method that forces you to provide all these important properties overriding a single method:
public class ComplexProperties
{
public string Table{ get; set; }
public string Fields{ get; set; }
public string Condition{ get; set; }
public string Group{ get; set; }
public string Order{ get; set; }
public DataGridViewColumnCollection Columns{ get; set; }
public SortedList<string, string> ComboboxFields{ get; set; }
}
public abstract partial class ReportsController()
{
public ComplexProperties Properties {get; private set;}
public ReportsController()
{
InitializeComponent();
//now your method
Properties= Init();
CheckProperties();
}
protected abstract ComplexProperties Init();
}
In any case I would prefer having a base constructor with parameters:
public abstract partial class ReportsController()
{
public ComplexProperties Properties {get; private set;}
public ReportsController(ComplexProperties properties)
{
Properties=properties;
CheckProperties();
}
}
And then initialize from the constructor:
public partial class MyReport:ReportsController
{
public MyReport():base(new ComplexProperties { Table="",...})
{
}
}
You could implement an interface for the properties that both the abstract base and the child classes need to implement.
Can I make some properties public only to same interface classes and readonly to all other classes?
You can use explicit implementation, for example:
interface IFoo {
int Value { get; set; }
}
public class Foo : IFoo {
public int Value { get; private set; }
int IFoo.Value {
get { return Value; }
set { Value = value; }
}
}
When accessed via Foo only the get will be accessible; when accessed via IFoo both getter and setter will be accessible.
Any use?
An interface is just something like a contract for classes. It doesn't change the accessibility level.
If a member of a class is public it is public to all classes that can access the class. The only restrictions you can have is the use of internal or protected. internal makes the member public to classes which are defined within the same assembly and protected makes it public to classes derived from the class.
Instead of the interface you can create an abstract base class and make the members protected:
public interface IFoo
{
int Value { get; set; }
}
public abstract class FooBase : IFoo
{
public abstract int Value { get; set; }
protected void ProtectedMethod()
{
}
}
public class Foo : FooBase
{
public int Value { get; set; }
}
However you can not define a member that is accessible by classes that implement a specific interface. There is no access modifier like public-to-IFoo-otherwise-private.
What is the proper way to implement an interface that has its own interface members? (am I saying that correctly?) Here's what I mean:
public Interface IFoo
{
string Forty { get; set; }
string Two { get; set; }
}
public Interface IBar
{
// other stuff...
IFoo Answer { get; set; }
}
public class Foo : IFoo
{
public string Forty { get; set; }
public string Two { get; set; }
}
public class Bar : IBar
{
// other stuff
public Foo Answer { get; set; } //why doesnt' this work?
}
I've gotten around my problem using explicit interface implementation, but I'm wondering if there is a better way?
You need to use the exact same type as in the interface:
public class Bar : IBar
{
public IFoo Answer { get; set; }
}
Note: IFoo instead of Foo.
The reason is that the interface defines a contract and the contract says that it must be an IFoo.
Think about it:
You have the classes Foo and Foo2, both implement IFoo. According to the contract, instances of both classes can be assigned. Now, if your code was legal, this would somehow break because your class only accepts Foo. Explicit interface implementation doesn't change that fact in any way.
You'll need to use generics to be able to do what you want.
public interface IFoo
{
string Forty { get; set; }
string Two { get; set; }
}
public interface IBar<T>
where T : IFoo
{
// other stuff...
T Answer { get; set; }
}
public class Foo : IFoo
{
public string Forty { get; set; }
public string Two { get; set; }
}
public class Bar : IBar<Foo>
{
// other stuff
public Foo Answer { get; set; }
}
This will allow you to provide an interface that says something like, "to implement this interface you must have a property with a public getter/setter of a type that implements IFoo." Without generics you are simply saying that the class has a property with a type of exactly IFoo, rather than anything that implements IFoo.
IBar has a IFoo field, not a Foo one, do this instead:
public class Bar : IBar
{
// other stuff
public IFoo Answer { get; set; }
}
Foo may extend type IFoo but that isn't what the interface exposes.
An interface defines a contract and you need to obey the terms of that contract.
So the correct way is to use
public IFoo Answer{get;set;} like others have said.