Solved

Abstract class inheritance

Posted on 2016-08-17
7
134 Views
Last Modified: 2016-08-30
I have multiple pages using the same code in a constructor as follow:
class LoginPage
    {
        public LoginPage(IWebDriver driver)
        {
            PageFactory.InitElements(driver, this);
        }
    }
class EmployeePage
 {
        public EmployeePage(IWebDriver driver)
        {
            PageFactory.InitElements(driver, this);
        }
 }

Open in new window

so I created a abstract base class first
public abstract class BasePage
    {
        public BasePage(IWebDriver driver)
        {
            PageFactory.InitElements(driver, this);
        }
    }

Open in new window


And then let other classes inherit this code instead of using the same code to each pages.
class LoginPage:BasePage
    {
        public LoginPage(IWebDriver driver): base(driver)
        {
        }
}

Open in new window


After I created a Login object, what's happening?
LoginPage lp = new LoginPage(_driver);

Open in new window


_driver is passed to LoginPage constructor which will call BasePage constructor.
It executes the code inside BasePage constructor and then execute the code inside LoginPage constructor.

Here is my question:
when it executes the code inside Base constructor with _driver, this will execute the following code for a base class, NOT for LoginPage class.
So it ends up initialize BasePage class NOT LoginPage class. I know that my logic is wrong. Can you please explain how executing the code in a base class initialize LoginPage class?
PageFactory.InitElements(_driver, this);

Open in new window

0
Comment
Question by:Isabell
  • 2
  • 2
  • 2
  • +1
7 Comments
 
LVL 143

Expert Comment

by:Guy Hengel [angelIII / a3]
ID: 41760587
I think that all you need to understand is that inside of :
PageFactory.InitElements(driver, this);
you need to check eventually the "GetType" of the passed object, to know it's exact class:
https://msdn.microsoft.com/en-us/library/system.object.gettype.aspx

I hope this is the point you are missing, as otherwise inheritance and calling a base constructor is "simple" ...
0
 
LVL 33

Accepted Solution

by:
sarabande earned 500 total points
ID: 41760902
So it ends up initialize BasePage class NOT LoginPage class.
your logic is incorrect since public inheritance means that LoginPage "IS" a BasePage, like a rabbit "IS" an animal and an animal "IS" a living being.

you may look at BasePage as a part of a LoginPage. actually this exactly is the case if both BasePage and LoginPage have data members. then you have a contiguous base structure with all BasePage members and an enlargement of the structure with all members of the LoginPage.

since c# doesn't support multiple inheritance, the 'this' 'points' to the begin of the memory object which starts with baseclass members followed by derived class members. so the 'this' points to both objects the smaller baseclass object and the larger derived class object and it is always the same object.

Sara
0
 
LVL 33

Expert Comment

by:it_saige
ID: 41761247
To illustrate Sara's point, consider the following:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

namespace EE_Q28964050
{
	class Program
	{
		static void Main(string[] args)
		{
			Animal critter = new Animal() { HasClaws = true, HasTeeth = true, IsHairy = true };
			Rabbit pet = new Rabbit() { HasClaws = true, HasTeeth = true, IsHairy = true, Name = "Fluffy" };

			Console.WriteLine("Is critter an Animal? {0}", critter.GetType().Equals(typeof(Animal)));
			Console.WriteLine("Is critter a Rabbit? {0}", critter.GetType().Equals(typeof(Rabbit)));
			critter.PrintProperties();

			Console.WriteLine();

			Console.WriteLine("Is pet an Animal? {0}", pet.GetType().Equals(typeof(Animal)));
			Console.WriteLine("Is pet a Rabbit? {0}", pet.GetType().Equals(typeof(Rabbit)));
			pet.PrintProperties();
			Console.ReadLine();
		}
	}

	class Animal
	{
		public bool IsHairy { get; set; }
		public bool HasTeeth { get; set; }
		public bool HasClaws { get; set; }
	}

	class Rabbit : Animal
	{
		public string Name { get; set; }
	}

	static class Extensions
	{
		public static void PrintProperties<T>(this T source)
		{
			if (source != null)
			{
				Console.WriteLine("Displaying properties for {0}", typeof(T).Name);
				foreach (PropertyInfo property in typeof(T).GetProperties())
					Console.WriteLine("Name: {0}; Value: {1}", property.Name, property.GetValue(source, null));
			}
		}
	}
}

Open in new window

Which produces the following output -Capture.JPG
-saige-
0
The New “Normal” in Modern Enterprise Operations

DevOps for the modern enterprise offers many benefits — increased agility, productivity, and more, but digital transformation isn’t easy, especially if you’re not addressing the right issues. Register for the webinar to dive into the “new normal” for enterprise modern ops.

 
LVL 33

Expert Comment

by:sarabande
ID: 41761292
Is pet an Animal? False

better:  Is pet an unknown or unspecified animal? False // no, it truly is a rabbit

;-)

Sara
0
 
LVL 33

Expert Comment

by:it_saige
ID: 41761470
You twisted my arm Sara...  ;).  Revised code to determine if instance derives from base class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

namespace EE_Q28964050
{
	class Program
	{
		static void Main(string[] args)
		{
			Animal critter = new Animal() { HasClaws = true, HasTeeth = true, IsHairy = true };
			Rabbit pet = new Rabbit() { HasClaws = true, HasTeeth = true, IsHairy = true, Name = "Fluffy" };

			Console.WriteLine("Is critter an Animal? {0}", critter.GetType().Equals(typeof(Animal)) || critter.GetType().BaseType.Equals(typeof(Animal)));
			Console.WriteLine("Is critter a Rabbit? {0}", critter.GetType().Equals(typeof(Rabbit)));
			critter.PrintProperties();

			Console.WriteLine();

			Console.WriteLine("Is pet an Animal? {0}", pet.GetType().Equals(typeof(Animal)) || pet.GetType().BaseType.Equals(typeof(Animal)));
			Console.WriteLine("Is pet a Rabbit? {0}", pet.GetType().Equals(typeof(Rabbit)));
			pet.PrintProperties();
			Console.ReadLine();
		}
	}

	class Animal
	{
		public bool IsHairy { get; set; }
		public bool HasTeeth { get; set; }
		public bool HasClaws { get; set; }
	}

	class Rabbit : Animal
	{
		public string Name { get; set; }
	}

	static class Extensions
	{
		public static void PrintProperties<T>(this T source)
		{
			if (source != null)
			{
				Console.WriteLine("Displaying properties for {0}", typeof(T).Name);
				foreach (PropertyInfo property in typeof(T).GetProperties())
					Console.WriteLine("Name: {0}; Value: {1}", property.Name, property.GetValue(source, null));
			}
		}
	}
}

Open in new window

Now produces the expected (and really correct output) -Capture.JPG-saige-
0
 

Author Comment

by:Isabell
ID: 41763363
Sara,

I really like your explanation:

since c# doesn't support multiple inheritance, the 'this' 'points' to the begin of the memory object which starts with baseclass members followed by derived class members. so the 'this' points to both objects the smaller baseclass object and the larger derived class object and it is always the same object.

Thanks!
0
 

Author Closing Comment

by:Isabell
ID: 41777311
sorry for the late acceptance. I thought that I did selected your answer long time ago.
Thank you again, Sarabande!
0

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Calculating holidays and working days is a function that is often needed yet it is not one found within the Framework. This article presents one approach to building a working-day calculator for use in .NET.
This article aims to explain the working of CircularLogArchiver. This tool was designed to solve the buildup of log file in cases where systems do not support circular logging or where circular logging is not enabled
In an interesting question (https://www.experts-exchange.com/questions/29008360/) here at Experts Exchange, a member asked how to split a single image into multiple images. The primary usage for this is to place many photographs on a flatbed scanner…
I've attached the XLSM Excel spreadsheet I used in the video and also text files containing the macros used below. https://filedb.experts-exchange.com/incoming/2017/03_w12/1151775/Permutations.txt https://filedb.experts-exchange.com/incoming/201…

829 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question