I'm reading a book in Design Patterns, and below is some code example used by the author. The author tries to build a html builder as (code in C#):
public class HtmlElement
{
public string Name, Text;
public List<HtmlElement> Elements = new List<HtmlElement>();
public HtmlElement() { }
public HtmlElement(string name, string text)
{
Name = name;
Text = text;
}
// factory method
public static HtmlBuilder Create(string name)
{
return new HtmlBuilder(name);
}
}
//builder class
public class HtmlBuilder
{
protected readonly string rootName;
protected HtmlElement root = new HtmlElement();
public HtmlBuilder(string rootName)
{
this.rootName = rootName;
root.Name = rootName;
}
public HtmlBuilder AddChild(string childName, string childText)
{
var e = new HtmlElement(childName, childText);
root.Elements.Add(e);
return this; //fluent api
}
// to return a HtmlElement object
public static implicit operator HtmlElement(HtmlBuilder builder)
{
return builder.root;
}
public override string ToString() => root.ToString();
}
then the author says:
"To simply force users to use the Builder whenever they are constructing a HtmlElement
object, we have hidden all constructors of HtmlElement
class as":
public class HtmlElement
{
...
protected HtmlElement() { }
protected HtmlElement(string name, string text)
{
Name = name;
Text = text;
}
...
}
so users can go like
HtmlElement root = HtmlElement.Create("ul").AddChildFluent("li", "hello").AddChildFluent("li", "world");
Console.WriteLine(root);
here is what I don't understand, the author changed the access modifier of HtmlElement
's constructors to protected
, which means that HtmlBuilder
class cannot access to the protected constructors like
protected HtmlElement root = new HtmlElement(); // not allowed
so does it mean that we need to let the HtmlBuilder
inherit from HtmlElement
? But they are no inheritance context at all, so how can I modify it?
1 Answer 1
If you don't need the class to be inherited from outside your library, you can use internal
, which will only allow it to be accessed within the same assembly.
If inheritance is required, you can use protected internal
instead (see C# docs)
The protected internal keyword combination is a member access modifier. A protected internal member is accessible from the current assembly or from types that are derived from the containing class. For a comparison of protected internal with the other access modifiers, see Accessibility Levels.
This makes it accessible within the assembly, but not from outside it.
And if you want to prevent inheritance outside of your assembly, you can use private protected
(see C# docs).
The private protected keyword combination is a member access modifier. A private protected member is accessible by types derived from the containing class, but only within its containing assembly. For a comparison of private protected with the other access modifiers, see Accessibility Levels.
Which allows you to inherit it in your assembly, but have the constructors private outside the assembly. Requires C# 7.2 compiler
Explore related questions
See similar questions with these tags.
public
access modifiers