如何在C#的CheckoutPage类中实现含方法与属性的Button成员
嘿,这个需求完全可以用匿名类实现,但具体写法得看你用的编程语言——我猜你大概率是在做UI自动化(比如Selenium),常用的Java、Kotlin、C#都有对应的实现方式,下面给你逐个拆解:
先看Java的实现(最贴合需求)
Java的匿名内部类支持直接实现接口,刚好能满足你要的方法+自定义getter逻辑:
首先在CheckoutPage里定义一个Button接口,然后用匿名类实现它,同时把私有XPath常量放在外部类里(或者匿名类内部):
public class CheckoutPage { // 私有XPath常量,只在CheckoutPage内部可用 private final String CHECKOUT_BUTTON_XPATH = "//button[@id='checkout-btn']"; // 公开的Button成员,用匿名类实现接口 public final Button button; public CheckoutPage() { button = new Button() { @Override public boolean displayed() { // 这里写判断元素是否显示的实际逻辑,比如用Selenium // return driver.findElement(By.xpath(CHECKOUT_BUTTON_XPATH)).isDisplayed(); return true; // 占位示例 } @Override public void click() { // 点击元素的实际逻辑 // driver.findElement(By.xpath(CHECKOUT_BUTTON_XPATH)).click(); } @Override public String getText() { // 自定义文本获取逻辑(比如处理隐藏文本、格式化等) // return driver.findElement(By.xpath(CHECKOUT_BUTTON_XPATH)).getText().trim(); return "Proceed to Checkout"; // 占位示例 } }; } // 定义Button接口,规范方法和getter private interface Button { boolean displayed(); void click(); String getText(); } }
调用方式完全符合你的要求:
CheckoutPage checkoutPage = new CheckoutPage(); boolean isButtonShown = checkoutPage.button.displayed(); checkoutPage.button.click(); String buttonText = checkoutPage.button.getText();
Kotlin的实现(完美贴合属性需求)
Kotlin的匿名对象支持实现接口,还能直接定义带自定义getter的属性,完全满足你的所有要求:
class CheckoutPage { private val checkoutButtonXPath = "//button[@id='checkout-btn']" // 用匿名对象实现Button接口 val button = object : Button { // 带自定义getter的Text属性 override val text: String get() { // 自定义获取逻辑,比如格式化文本 // return driver.findElement(By.xpath(checkoutButtonXPath)).text.trim() return "Proceed to Checkout" } override fun displayed(): Boolean { // 实际显示判断逻辑 // return driver.findElement(By.xpath(checkoutButtonXPath)).isDisplayed return true } override fun click() { // 实际点击逻辑 // driver.findElement(By.xpath(checkoutButtonXPath)).click() } } // 定义Button接口 private interface Button { fun displayed(): Boolean fun click() val text: String } }
调用方式完全符合预期:
val checkoutPage = CheckoutPage() checkoutPage.button.displayed() checkoutPage.button.click() val buttonText = checkoutPage.button.text
C#的实现(有小限制)
C#的匿名类不能直接实现接口,而且属性只能是初始化时的固定值——如果想要自定义getter的Text属性,没法直接做到,只能用Func<string>模拟成方法调用;如果接受Text是方法而不是属性,那写法如下:
public class CheckoutPage { public dynamic Button { get; } public CheckoutPage() { // 私有XPath常量 string checkoutButtonXPath = "//button[@id='checkout-btn']"; Button = new { // 实现Displayed方法 Displayed = new Func<bool>(() => { // 实际逻辑:return Driver.FindElement(By.XPath(checkoutButtonXPath)).Displayed; return true; }), // 实现Click方法 Click = new Action(() => { // 实际逻辑:Driver.FindElement(By.XPath(checkoutButtonXPath)).Click(); }), // 用Func模拟自定义getter的Text(调用时是Text()而不是Text) Text = new Func<string>(() => { // 实际逻辑:return Driver.FindElement(By.XPath(checkoutButtonXPath)).Text.Trim(); return "Proceed to Checkout"; }) }; } }
调用时注意Text是方法:
var checkoutPage = new CheckoutPage(); bool isDisplayed = checkoutPage.Button.Displayed(); checkoutPage.Button.Click(); string buttonText = checkoutPage.Button.Text();
如果必须要Text作为属性访问(checkoutPage.Button.Text),那C#的匿名类做不到,得老老实实写命名的Button类或者用接口+实现类。
匿名类方案的优缺点
- 优点:不用单独维护一个独立的
Button类,代码更内聚,适合这个Button只在CheckoutPage里使用的场景。 - 缺点:复用性差,如果其他页面也需要类似的Button,没法直接复用;调试时匿名类的名称不够直观;C#里对属性的支持有限。
内容的提问来源于stack exchange,提问作者Chubosaurus Rex
相关产品推荐
相关产品推荐

