This question is about OOP in any statically typed language. Suppose I have two classes whose instances maintain pointers/references to each other. In my case, one class is a container, and the other a wrapper around a contained object which maintains a pointer to the container in which it lives.
class Container {
Element[] elements;
}
class Element {
// ... data...
Container holds_me;
}
The constructor of Container creates an Element object to wrap each contained object, and sets their holds_me pointers to itself.
Now I want to inherit from these classes. I want a DerivedContainer class, which inherits from Container and contains DerivedElement objects, where DerivedElement inherits from Element and refers to the containing DerivedContainer object. What is the right way to do this (or is it the wrong thing to do)?
The most straightforward thing is for the constructor of DerivedContainer to create DerivedElements and store them in elements and set their holds_me pointer to itself. Then all the methods of Container and Element will work, but any new methods defined in DerivedContainer and DerivedElement will have to downcast the objects held in elements and holds_me in order to invoke any new methods on them that weren't defined in the base classes. This doesn't seem pretty; so I wonder, is there a better solution?
Yep, this is the right way to do it, without any more information, IMHO. It makes sense if you think that all of the methods in Element can apply to every Element, but the only classes that should know anything about the Derived set of functionality are (ideally only) DerivedElement and (if necessary) DerivedContainer. In other words, to anyone else, Elements and Containers are only Elements and Containers.
You can sometimes do a little better with templates(C++) or generics(Java), since the thought behind these features is that a Container<Element> knows that it holds Elements and a Container<DerivedElement> knows that it holds DerivedElements, but if you have a heterogeneous Container, you really have to have each subclass handle the derived functionality by trying to downcast.
If your language supports it, you could use Generics/Templates. The Container class could have the Elements class as a parameterized type. That way, you can forget about downcasting the Elements.
In case anyone is interested, I've realized that it's possible to do more or less what I originally wanted here using abstract types. Here is some Scala code:
abstract class Container { ctnr =>
type E <: Element
class Element { this : E =>
// data
def holds_me = ctnr
}
var elements : Array[E]
}
The original container is an abstract class containing both a nested class of elements and an abstract type of elements. The subtyping assertion E <: Element requires E to always be a subclass of Element, while the self reference this : E => forces any instantiation of Element to belong to the type E (as instantiated by some implementation of Container).
class ContainerImpl extends Container {
type E = Element
// initialize 'elements' using 'new Element()'
}
abstract class DerivedContainer extends Container {
override type E <: DerivedElement
class DerivedElement extends Element { this : E =>
// more data
}
}
class DerivedContainerImpl extends DerivedContainer {
type E = DerivedElement
// initialize 'elements' using 'new DerivedElement()'
}
Related
sealed class DestinationScreen(val route:String){
object Signup: DestinationScreen(route = "signup")
}
Now I am developing navigation screen above.
I don't understand this statement.
object Signup: DestinationScreen(route = "signup")
I think Signup is property. So to set it, should we write this below?
object Signup = DestinationScreen(route = "signup")
Why does not using = issue the instance and set the Signup property?
Please teach me. Thank you.
Nope. Signup is not a property. It's basically a class which extends DestinationScreen except it's a special class object which acts as a singleton and is initiated at the same point it's described. That's why you write it like that.
Why it looks like a property to you is you happen to declare it in another class (which makes it an inner class). But you can declare it outside of the class too.
More about Kotlin objects https://kotlinlang.org/docs/object-declarations.html
Sealed classes represent a class with a fixed number of subclasses. At first, you declare the parent class, for example, a class that describes Screen of your app. Then, you declare all children of this class. For example, HomeScreen and LoginScreen:
sealed class Screen
class HomeScreen : Screen()
class LoginScreen : Screen()
All subclasses can be written outside of the parent class (but must be located in the same file due to compiler limitations).
You can use the object keyword instead of class modifier in case of a class has no properties. It means that the object keyword declares a singleton class.
Because you are using inheritance, not an assigment.
A sealed class is a class which subtypes are known by the compiler so it allows you to create flow controls by type:
sealed class Result {
data class Success(val data...): Result()
data class Error(val exception...): Result()
}
So you can do:
when(val result = ...) {
is Success -> result.data
is Error -> result.error
}
Whith normal inheritance like on interfaces, open classes or abstract classes you dont know the typed thar inherit from the super type.
I've recently run into some examples that make use of abstract classes as interfaces but also add factory constructors to the abstract interface so it can in a sense be "newed" up. For example:
abstract class WidgetService {
factory WidgetService() = ConcreteWidgetService;
Widget getWidget();
void saveWidget(Widget widget);
}
class ConcreteWidgetService extends BaseWidgetService implements WidgetService {
WidgetService();
Widget getWidget() {
// code to get widget here
}
void saveWidget(Widget widget) {
// code to save widget here
}
}
Usages of this service would be in some other service or component like so:
WidgetService _service = new WidgetService();
Based on my understanding of this sample, the line above would essentially "new" up a WidgetService, which usually produces an warning from the Dart analyzer, and said service variable would actually be an instance of ConcreateWidgetService based on the assignment of the ConcreateWidgetService to the factory constructor of the WidgetService.
Is there a benefit to this approach? From my OOP experience, I've used abstract classes/interfaces to program against when I didn't know the concrete type I would be given. Here it seems we are assigning the concrete type immediately to the abstract factory constructor. I guess my second question would be in this instance why not just use the ConcreteWidgetService directly here instead of repeating all the method signatures?
In your example the benefits are limited but in more complex situations the benefits become more clear.
A factory constructor allows you more control about what the constructor returns. It can return an instance of a subclass or an already existing (cached) instance.
It can return different concrete implementations based on a constructor parameter:
abstract class WidgetService {
WidgetService _cached;
factory WidgetService(String type) {
switch (type) {
case 'a':
return ConcreteWidgetServiceA();
case 'b':
return ConcreteWidgetServiceB();
default:
return _cached ??= DummyWidgetServiceA();
}
}
Widget getWidget();
void saveWidget(Widget widget);
}
Your example seems to be a preparation to be extended eventually to such a more flexible approach.
In Dart, all classes are also automatically interfaces. There's nothing strange about creating a instance of - 'newing up' - an 'interface', because it's actually just creating an instance of a class.
The purpose of some abstract classes is specifically to define an interface, but they have factory constructors that return a 'default implementation' of themselves.
For instance:
void main() {
var v = new Map();
print(v.runtimeType);
}
prints: _InternalLinkedHashMap - the (current) default implementation of Map.
Core library users can create and using instances of Map without knowing or caring about the implementation they actually get. The library authors may change the implementation without breaking anyone's code.
Of course, other classes may implement Map also.
With respect to your code sample, WidgetService _service = new WidgetService(); does not produce an analyzer warning. See this example on DartPad (Note I fixed a couple of errors in your sample).
I was initially confused by:
factory WidgetService() = ConcreteWidgetService;
instead of:
factory WidgetService() => new ConcreteWidgetService();
but it seems to work.
Is it allowed to call components' components according to the Law of Demeter?
By component I mean an object
which was "exclusively" injected into the container or was created in
the container
which has the same life cycle with it's container
For example, Brain is a component of a Dog:
partial class Dog
{
private readonly IBrain brain;
public Dog(IBrain brain)
{
this.brain = brain;
}
}
Here is some information I found:
http://c2.com/cgi/wiki?LawOfDemeter
Your method can call methods on its own fields directly (but not on
the fields' fields)
message target can only be one of the following objects:
... an object referred to by the object's attribute
http://www.ccs.neu.edu/research/demeter/demeter-method/LawOfDemeter/paper-boy/demeter.pdf
A method of an object should invoke only the methods of the following
kinds of objects:
...
any objects it creates/instantiates
its direct component objects
And here is a case:
partial class Dog
{
public void Command(string cmd)
{
var movement = brain.GetMemory().GetMovement(cmd);
skeleton.ExecuteMovement(movement);
}
}
Is it allowed to call components' components according to the Law of Demeter?
By definition this is not allowed since you should Only talk to your immediate friends.
In other words, the IBrain service should not expose its internal services through its interface (assuming that GetMemory() returns an IMemory service of some kind). Instead, the IBrain interface should either provide provide a method that allows retrieving the movement -or- the IMemory should be injected directly intoDog`.
When you're instantiating an object of a class that inherits from a parent class the constructor calls the superclasses constructor in most langiages I know and my question is: when the superclasse's constructor is called there will effectively be an object of that type in memory, but we're creating an object of the subclass with(in this example) additional values to add to the object so how is that accomplished in memory? Is it added to the original object? Are the contents of the original object copied into a new object with space for all the variables? Or is it something completely different?
A different question that just occured to me, are class variables, like in java, kept in the data segment of the program in memory? How are classes, not the objects, stored in memory for that matter?
Thanks.
I don't really know how engine works, but I know how to test memory usage in PHP. Both scripts
class base {
public function __construct() {
}
}
$start_memory = memory_get_usage();
$object = new base;
echo memory_get_usage() - $start_memory;
and
class base {
public function __construct() {
}
}
class derived extends base {
public function __construct() {
}
}
$start_memory = memory_get_usage();
$object = new derived;
echo memory_get_usage() - $start_memory;
return the same value. It means there'is only one instance in memory, not parent + it's child, when class is extended
phpfiddles: 1st script, 2nd script
Classed are code that define its object, so they are in Code Segment of program. And all class variables are in data segment.
And when we create an object of subclass, first its parents' object are created and it is extended for subclass members. That's why subclass object has all members of its parent class.
I have a parent bean having one instance variable like below :
public Class ParentBean {
protected boolean show; // this variable will be used to show some UI component
public void action() {
// update show variable here
}
public boolean isShow() {
return show;
}
}
Is it a good design if I want to reuse the "show" variable in a child bean (to show other UI component specific to child bean ) as shown below :
public Class ChildBean extends ParentBean {
// override the action method from parent bean
public void action() {
// update show variable here
show = true /false;
}
}
In effect , show variable is being updated by "childBean" by overriding action() method.
Is this a good design practice ? Otherwise same thing has to be repeated in ChildBean to get this work done.
If you use the show variable for the same purpose in the subclass, as you seem to be doing in this example, then obviously you should reuse it, because otherwise you just end up writing the same code twice, which is contrary to the point of OOP.
In general, in OOP, it is common to override superclass methods in subclasses, as well as modifying superclass instance variables, as long as you know what the variable you are modifying is being used for (you don't want to be randomly changing instance variables in classes that you don't completely understand, or don't have access to the source of, because you don't want any unfortunate side effects), so when it's your own code, this is absolutely fine.
As a general guideline, if your options are either to copy and paste a massive hunk of code and use it unchanged, or subclass and use the superclass' instance variables or functions, it's better to subclass. Otherwise, you're missing out on the point of OOP.
Changing the value in subclass will not affect superclass variable
This is fine with respect to the design. When a subclass object is instantiated, it will have a different copy of variable. and If superclass object is instantiated it will have different copy.
It is. Having a protected variable means you are allowed to modify it into parent or children classes (remember every single instance of each class has its own property values). So, if you have some generic functionality which is valuable for all the children:
Parent class:
public void action(){
//update show variable here
show = true;
}
Appart from that, if you want to add some extra functionality in a specifical child:
Child class:
#Override
public void action(){
super.action();
//Extra functionality goes here
//You can also access parent's 'protected' fields
if (show){
System.out.println("Shown");
}
}
An example of the use:
Parent p = new Parent();
p.action();//Prints nothing
Child c = new Child();
p.action();//Prints 'shown'