I have a need where I would like to have a base class only available to one specific subclass. This is due to a limitation where you cannot define an Attribute as an inner class of a generic.
The reason we want to define the attribute within the generic is when you do that and set its type to protected, that attribute is now only available to subclasses of your base class, keeping your API clean.
As an example, consider the abstract class ExampleMarkupExtension<T> that inherits from MarkupExtension. I want to define the attribute StaticInfoAttribute as an inner class, so it is only available to subclasses of ExampleMarkupExtension<T>.
However, as mentioned, you can't define an attribute as an inner class of a generic, so my workaround is to create a second, non-generic ExampleMarkupExtensionBase class which inherits from MarkupExtension, define StaticInfoAttribute as an inner class there, then have the generic inherit from that class instead.
The issue is now I have an extra class in my hierarchy that anyone can subclass. While it's technically harmless, I like keeping my API surface area clean.
Example
ExampleMarkupExtensionBase : Non-generic abstract base class
This is the class that defines the attribute which should only be available to subclasses of this class. This class only exists because I can't put StaticInfoAttribute within the generic abstract base class ExampleMarkupExtension<T> below.
public abstract class ExampleMarkupExtensionBase : MarkupExtension {
[AttributeUsage(AttributeTargets.Class, AllowMultiple=false, Inherited=false)]
protected class StaticInfoAttribute : Attribute {
public StaticInfoAttribute(string value) => Value = value;
public readonly string Value;
}
}
ExampleMarkupExtension<T> : Generic abstract base class
This is the class that holds the static members which are unique to the subclasses of this class. It does this by using the subclass as the type parameter for the base class (see the where clause). The value of the static field is set from the attribute, hence it only being of any use for this specific subclass of ExampleMarkupExtension above.
public abstract class ExampleMarkupExtension<T> : ExampleMarkupExtensionBase
where T : ExampleMarkupExtension<T> {
static ExampleMarkupExtension() => Value = typeof(T).GetRequiredCustomAttribute<StaticInfoAttribute>().Value;
public static readonly string Value;
public sealed override object ProvideValue(IServiceProvider serviceProvider)
=> Value;
}
Rationale
Some may ask what's the harm of leaving it as-is. Technically, there's nothing wrong with letting a person subclass ExampleMarkupExtensionBase. There's just no point to it.
For that matter, there's technically no harm with moving the StaticInfoAttribute outside of the class as well, removing the need for the non-generic base class entirely. I just chose the former approach as it's more important to restrict the attribute's usage than it is to stop someone from subclassing the base class.
As per our comments, you can use the EditorBrowsable attribute to hide the method from projects that reference it. Note however it just hides it from IntelliSense and if a user was to type out ExampleMarkupExtensionBase that the class still exists and is valid to be used.
[EditorBrowsable(EditorBrowsableState.Never)]
public abstract class ExampleMarkupExtensionBase : MarkupExtension
Related
I have the following situation:
I have a base read-only class with simple information
I have a second class that inherits from the base class, this class' members can be updated
public class ExtendedClass : BaseClass
{}
To check if a class can be updated I have an abstract class UpdatableRecord
This abstract class has a property RecordState ("Deleted", "Edited", "New", "None")
this property has the default value "deleted".
What is the best way to build the classes (use different interfaces?, how is the hierarchy?)
Constructors of an abstract class shouldn't be public and they should be protected. My question is about methods in that abstract class. Can we declare them as public or they should be protected too for the same reason?
The justification for constructors on abstract types being protected is that there is simply no other entity that could call the constructor other than a derived type. Making the constructor public is meaningless in this case as it can't ever be invoked outside the type hierarchy. Hence the recommendation is to use protected as it's the most appropriate access modifier.
The same logic doesn't hold true with other members on the type. They can be freely invoked from outside the type hierarchy should their access modifier permit it.
public abstract class Dog {
// Public is appropriate here as any consumer of Dog could access
// Breed on an instantiated object
public abstract string Breed { get; }
// Public would be meaningless here. It's not legal to say
// 'new Dog' because 'Dog' is abstract. You can only say
// 'new Poodle' or 'new Bulldog'. Only derived types like
// Poodle or Bulldog could invoke the Dog constructor hence it's
// protected
protected Dog() { }
}
public class Poodle : Dog { }
public class Bulldog : Dog { }
Whether or not a particular member should be public or protected is highly dependent upon the particular API. The reasoning should be the exact same for abstract types as it is for non-abstract types
Abstract classes shouldn't have public constructors because they don't make sense. Abstract classes are incomplete, so allowing a public constructor (which anyone could call) wouldn't work as you can't instantiate an instance anyway.
Methods on abstract classes are another story. You can have implementation in an abstract class, which is the behavior that all subclasses will inherit. Think of a Shape class. Its purpose is to draw a shape on the screen, so it makes sense to make a Draw method public as you'll want callers to be able to ask your Shape to draw. The method itself can be abstract, forcing subclasses to implement, or possibly provide an implementation which may or may not allow overriding. It depends on what the defined behavior of your class should be.
It depends on your use case. If you want the methods of the abstract class visible to instances of your derived class, you should make them public. If, on the other hand, you want the methods visible only to your derived class, you should make them protected.
I had created a base class that has many public properties and were been used perfectly. Now i want to use this class to derive other class , but i do'nt want some of its properties to be exposed outside the derived class that inherits it. Is there any way that the properties of base class that are public cannot be exposed outside its derived class.(The properties that are to be hidden are public because they are used in other classes that inherits it).Any help will be highly appericiated.
You want to make them protected.
From MSDN:
A protected member is accessible within its class and by derived class instances.
I agree with cadrell0 about marking them protected, but just in case you are looking for a solution where the properties are actually public, but hidden to users of a certain derived class, you can use an explicit interface
interface IHaveMethodsYouCanHide { void Foo(); }
class Base : IHaveMethodsYouCanHide { public void Foo() {} }
class NonHidingDerived : Base { }
class HidingDerived : Base, IHaveMethodsYouCanHide
{
void IHaveMethodsYouCanHide.Foo() {}
}
With this code, identifers of type HidingDerived will not allow calls to Foo (unless first cast to IHaveMethodsYouCanHide).
What you're asking for is simply not possible. If type B inherits from type A then it "is-a" type A. B has at least the same accessible contract that type A had. There is no way to hide a public member of A without fundamentally violating this contract.
If you find yourself in a scenario where you want to use A but only expose a subset of the properties then inheritance is not the right solution: containment is the proper solution.
public class B {
private A m_wrapped;
// Expose only the properties you want to expose here
}
I have a base object abstract class and a base object collection class for some business objects to inherit from. I'm trying to figure out how to pass the base object type to the collection class (and other methods). I've been able to solve this by wrapping the class in an interface but i'm wondering if there is another way to do this or if using an interface is the best way. i think my question might make more sense from the code below.
i have a base class define -
public abstract class BaseObject<TYPE,KEY>:where TYPE:BaseObject<TYPE,KEY>, new()
public KEY ObjectId {get;protected set; }
i have a class that inherits from BaseObject
public class Customer : BaseObject<Customer,Guid>
My base collection class is -
public abstract class BaseObjectCollection<T> : List<T> where T: BaseObject, new()
I also have a few methods in other class that want to reference this baseclass -
public bool ValidateRule(BaseObject dataObject) {etc...}
If you use the base class in other classes that are not also generics, then I'm afraid that you're going to have to specify the type and key parameters for the object when you pass it to methods like ValidateRule.
In this design, an Interface implemented by the base object is probably the most appropriate solution. We use this pattern extensively in our code and it works quite well.
One other item you could explore is reducing the complexity of the base class slightly by moving the Key into the class as an overridable (or must override) property that defaults to a string or int or whatever may be appropriate. We found that this approach (we forced all collection keys to be strings) significantly reduced the class complexity.
I am sorry if I am asking something stupid but I am completely a newbie in C# and ASP.NET.
I am having an error in my code and I don't understand it.
I am working on Visual Studio 2008.
In this line of code:
public class SQLFAQProvider : DBFAQProvider
I am getting this error:
Moby.Commerce.DataAccess.FAQ.SQLFAQProvider does not implement inherited abstract member Moby.Commerce.DataAccess.FAQDBFAQProvider.DeleteFAQbyID(int)
When I go to DBFAQProvider the error is in this line of code:
public abstract DBFAQ DeleteFAQbyID(int fAQID);
What should I change to correct it?
First thought would be implement the abstract member in the inherited class ala:
public class SQLFAQProvider : DBFAQProvider
{
public override DBFAQ DeleteFAQbyID(int fAQID)
{
//TODO: Real Code
return null;
}
}
Implement the DeleteFAQbyID method in your derived class:
public override DBFAQ DeleteFAQbyID(int fAQID)
{
// Put your code here
}
The point of an abstract method is to say (in the abstract base class), "I want to make sure that this method is available in every concrete class deriving from me" - it's up to you to provide the implementation. It's a bit like a method in an interface.
Your subclass needs to explicitly implement that particular method.
If you have no idea how to do it, then at least do:
public override DBFAQ DeleteFAQbyID(int fAQID)
{
throw new NotImplementedException("This isn't done yet");
}
When you inherit from a class in C#, you are required to implement all methods marked as abstract unless your class is itself marked as abstract. Abstract classes are ones that cannot be directly instantiated at runtime because they don't fully implement all of the required methods that the base class(es) say must exist.
Abstract methods are a mechanism that allows a class to indicate that a particular method must "eventually" exist - without having to provide an implementation at that point. You typically use abstract classes when you cannot or don't want to dictate what a particular implementation should do, but you need to pre-define a method that you will eventually rely on.
To fix your problem either mark your class as abstract (with the expectation that another level of inheritance will fill in the missing pieces) or implement DeleteFAQbyId() in your class:
public DBFAQ DeleteFAQbyID(int fAQID)
{
// write appropriate implementation here or:
throw new NotImplementedException();
// or possibly NotSupportedException() if the operation should can't ever be supported.
}
When a class inherits from an abstract class it must implement all abstract methods defined by said class. This is the class interface, the abstract methods can be thought of as pure virtual functions, i.e., functions that must be implemented by descended classes but do not make sense to be implemented in the base class.
Because your SQLFAQProvider class isn't abstract, it has to implement every abstract method that it inherits.
To fix this, implement the DeleteFAQbyID method in SQLFAQProvider, like this:
public override DBFAQ DeleteFAQbyID(int fAQID) {
//Do something
}
Alternatively, you could make your SQLFAQProvider class abstract by changing its declaration to public abstract class SQLFAQProvider.
Your subclass (SQLFAQProvider) must provide implementation code for the method DeleteFAQbyID because the parent class (DBFAQProvider) did not.
In the abstract class use an entity property like IsValid. Make it return the abstract method that you want to override in the derived class.
In abstract base class:
public bool IsValid
{
get
{
return DeleteFAQbyID();
}
}
public abstract bool DeleteFAQbyID();
In the derived class now it will override the abstract class' method.